Skip to content
Florian Sellmayr edited this page Jan 22, 2017 · 8 revisions

Overview

The event-bus can be used to pass around or react to events happening in LambdaCD, such as updates to the state of a pipeline run.

It's based on the core.async pub/sub abstraction (a good introduction can be found here).

A few things to keep in mind when working with the event-bus:

  • Subscriptions are unordered and parallel: You can not assume that other event-handlers already processed the same event
  • Subscriptions block the publisher: If you are subscribing to an event, make sure you process it quickly as the publisher is only unblocked after all subscribers processed the event

Usage

The main entry-point is the lambdacd.event-bus namespace with convenience-functions to publish and subscribe to events:

  • publish [ctx topic payload]: Publishes an event with a given payload for a particular topic
  • subscribe [ctx topic]: Returns a channel with a subscription for events with the given topic. The events on this channel contain the payload and metadata about the event (e.g. the topic)
  • only-payload [subscription]: Takes a channel (usually the result of subscribe) and returns a channel that contains only the payload for the event
  • unsubscribe [ctx topic subscription]: Unsubscribe from a topic. Takes the result of subscribe and the topic subscribed to

Events:

Currently, the following topics are provided by LambdaCD:

  • :step-finished: Event that gets triggered after a build step is finished. Can be used to trigger notifications in other systems or to react a finished build step. For example used by runners to determine when to start a new pipeline-run. The payload looks like this:

    {:build-number 3
     :step-id `(1 2 3)
     :final-result {:status :success :foo :baz}}
  • :step-result-updated: Event that gets triggered whenever a step updates it's result. For example used by pipeline-state components to save updates to the pipeline state to disk. As event-handlers are unordered, you can not assume that these components already processed this event. Look at :step-result-update-consumed as an alternative. The payload looks like this:

{:build-number 3 :step-id `(1 2 3) :step-result {:status :running}}

* `:step-result-update-consumed`: Event that gets triggered whenever a step-result update has been consumed by the pipeline state component. Pipeline is the same as `:step-result-updated`. Prefer this event over `:step-result-updated` if you expect the update to be present in the pipeline state. (introduced in 0.11.0)
* `:pipeline-started`: Event that gets triggered whenever a new build-pipeline gets started (this includes retriggered builds). (introduced in 0.13.0) The payload looks like this: 

```clojure
{:build-number 10}
  • :pipeline-finished: Event that gets triggered whenever a build-pipeline finishes. (introduced in 0.13.0) The payload looks like this:

    {:build-number 10  
     :status  :success
     :outputs {[1] {:status :success
                    :step   1}
               [2] {:status :success
                    :step   2}}}

Custom topics

Build pipelines or components can define their own classes of events just by publishing events to a topic of their choosing. For example, the manual trigger uses this to notify build steps waiting for a user interaction once the user has clicked the trigger button in the UI.

Example

; Print all events to topic :foo-topic
(ns events-example.core
  (:require
    [lambdacd.core :as lambdacd]
    [lambdacd.event-bus :as event-bus]
    [clojure.core.async :as async]))

(defn print-all-foo-events [ctx]
  (let [subscription (event-bus/subscribe ctx :foo-topic)
        steps-finished (event-bus/only-payload subscription)]
    (async/go-loop []
      (if-let [event (async/<! steps-finished)]
        (do
          (println event)
          (recur))))))

(defn -main [& args]
  (let [pipeline (lambdacd/assemble-pipeline pipeline/pipeline-def config)]
    ; ...
    (print-all-foo-events (:context pipeline))))

; Publishing an event on :foo-topic
(ns events-example.steps
  (:require [lambdacd.event-bus :as event-bus]))

(defn some-step-that-publishes-foo [args ctx]
  (event-bus/publish ctx :foo-topic {:some :data})
  {:status :success})