Events API » History » Version 2
Tom Clegg, 10/19/2016 10:24 AM
1 | 1 | Tom Clegg | h1. Events API |
---|---|---|---|
2 | |||
3 | (draft) |
||
4 | |||
5 | {{toc}} |
||
6 | |||
7 | See also: [[Websocket server]] |
||
8 | |||
9 | h1. Purpose |
||
10 | |||
11 | The Events API serves to notify processes about events that interest them _as soon as possible after those events happen_. |
||
12 | |||
13 | (The history of events that have happened in the past is also interesting, but that's addressed by the Logs API, not the Events API.) |
||
14 | |||
15 | h1. Conceptual model |
||
16 | |||
17 | An event reports a change to the state of an object. |
||
18 | |||
19 | The fact that an object's state has changed is meaningful only when its previous state is known. For example, if a client asks "tell me the next time object X changes" at nearly the same time X changes, the response depends on whether the request arrives before or after the change occurs. |
||
20 | |||
21 | Therefore, the Events API should support operations like: |
||
22 | * "tell me the current state of X, and then notify me next time it changes" |
||
23 | * "tell me as soon as X differs from my cached copy that has Etag E" |
||
24 | |||
25 | An "event stream" is a sequence of events about an object, starting from an implicit or explicit known state. |
||
26 | |||
27 | h1. Essential features |
||
28 | |||
29 | h2. Multiple streams |
||
30 | |||
31 | The Events API supports multiplexing event streams on a single connection. The cost of setting up and maintaining an event channel can be non-trivial, and the sequence of events concerning multiple related objects may be significant. |
||
32 | |||
33 | It is possible to add and remove event streams on an existing connection, without interrupting other streams. |
||
34 | |||
35 | It is permitted to hold a connection open with no event streams, but the server may close such connections after some time threshold. |
||
36 | |||
37 | h2. Delivery guarantees |
||
38 | |||
39 | In general, the Events API cannot guarantee that every event will be delivered. |
||
40 | |||
41 | However, there are specific cases where it is possible to detect missed events and notify the client. |
||
42 | |||
43 | If some events are dropped but the event stream is still open (for example, a server-side buffer overflows when a client is receiving data too slowly) the stream must indicate this to the client as soon as possible, and no later than the next event. |
||
44 | * The "missed events" signal does not necessarily specify the number of missed events. |
||
45 | * The server is permitted to send a "missed events" signal even if no events were missed. |
||
46 | |||
47 | Depending on the application, a client might respond to a "missed events" signal by |
||
48 | * restarting the affected streams immediately |
||
49 | * restarting the affected streams only if they stay silent for some timeout period |
||
50 | * doing nothing |
||
51 | * hanging up |
||
52 | |||
53 | h2. Event message content |
||
54 | |||
55 | Each event includes the UUID and Etag of the changed object. |
||
56 | |||
57 | If requested by the client, and supported by the server, events may also include other object attributes. |
||
58 | |||
59 | h1. Additional features |
||
60 | |||
61 | h2. Event sequence |
||
62 | |||
63 | With the current API server, it may be possible to update an object twice in quick succession such that the modification timestamps are out of order: i.e., the current state of object X has modification time T1, even though the same object previously had modification time T2>T1. If this occurs, the Events API must return the T2 update before the T1 update (or not return the T2 update at all). |
||
64 | |||
65 | In order to support delivery mechanisms where messages are re-ordered in transit, the Events API should assign a strictly increasing integer ID to each event sent over a given connection. Client pseudocode: |
||
66 | |||
67 | <pre> |
||
68 | receiveEvent(id, uuid, newEtag): |
||
69 | if lastID[uuid] > id: |
||
70 | # already received a newer update for this object |
||
71 | return |
||
72 | currentEtag[uuid] = newEtag |
||
73 | lastID[uuid] = id |
||
74 | </pre> |
||
75 | |||
76 | Note these IDs are connection-specific: they cannot be used to reconnect and resume an event stream. |
||
77 | |||
78 | h2. Server-side event filters |
||
79 | |||
80 | Some clients will only be interested in a subset of possible changes. For example, a pipeline runner wants to know as soon as a container's "state" attribute changes, but might not care about other changes like "priority" or "progress". |
||
81 | |||
82 | Possible API features for reducing unnecessary work and network traffic: |
||
83 | # Allow clients to describe which attributes are interesting, e.g., @"select":["state"]@ |
||
84 | # With each event, provide the list of changed attributes, e.g., @"changed":["state","output","log"]@, but not the attribute values themselves |
||
85 | |||
86 | These features might be tricky to implement efficiently for attributes that are computed on the fly. |
||
87 | |||
88 | h2. Null stream |
||
89 | |||
90 | To simplify implementation of clients that subscribe to event streams but also retrieve some objects without listening for events, a client should be able to use the Events API to retrieve the current state of an object without subscribing to the object's event stream. |
||
91 | 2 | Tom Clegg | |
92 | h2. Ownership-change events |
||
93 | |||
94 | Some clients need to know when an object is added or removed from a project. |
||
95 | |||
96 | When an object's owner_uuid changes, this event should be sent to: |
||
97 | # all clients subscribed to the object itself |
||
98 | # all clients subscribed to the old owner_uuid |
||
99 | # all clients subscribed to the new owner_uuid |
||
100 | |||
101 | Likewise, subscribing to stream X should cause clients to receive messages when a new object is created with owner_uuid=X, and when an object with owner_uuid=X is deleted. |