diffusion
Version:
Diffusion JavaScript client
1,249 lines (1,213 loc) • 48.3 kB
JavaScript
var _interface = require('util/interface')._interface;
/**
* This feature allows a session to update and query time series topics.
*
* <h2>Time series topics</h2>
* <p>
* A <em>time series</em> is a sequence of events. Each event contains a value
* and has server-assigned metadata comprised of a sequence number, timestamp,
* and author. Events in a time series are ordered by increasing sequence
* number. Sequence numbers have values between <code>0></code> and
* <code>Number.MAX_INTEGER</code> and are contiguous: an event with sequence number
* <code>n</code> will be followed by one with sequence number <code>n + 1</code>. Two
* events with the same sequence number will be equal – having the same
* timestamp, author, and value.
*
* <p>
* A time series topic allows sessions to access a time series that is
* maintained by the server. A time series topic has an associated
* {@link diffusion.datatypes.DataType event data type}, such as <code>Binary</code>, <code>String</code>, or
* <code>JSON</code>, that determines the type of value associated with each event.
*
* <p>
* This feature provides a historic query API for time series topics, allowing a
* session to query arbitrary sub-sequences of a time series. The
* {@link Session.topics} and {@link Session#addStream} features complete the API, providing
* ways to create and subscribe to a time series topic.
*
* <p>
* The API presents a time series as an append-only data structure of immutable
* events that is only changed by adding new events.
*
* <h3>Edit events</h3>
*
* <p>
* Although a time series is append-only, an event can be overridden by
* appending an <em>edit event</em>. An edit event is a special type of event
* that overrides an earlier event in the time series (referred to as the
* <em>original event</em>) with a new value. When an edit event is added to a
* time series, the server retains both the original event and the edit event,
* allowing subscription and query results to reflect the edit.
*
* <p>
* For example, suppose a time series has two events with the values <code>A</code>
* and <code>B</code>, and the first event has been overridden by a later edit event
* that provides a new value of <code>X</code>. The server has the following
* information about the time series.
*
* <p>
* <table>
* <tr>
* <th>Sequence</th>
* <th>Value</th>
* <th>Type</th>
* <th></th>
* </tr>
* <tr>
* <td>0</td>
* <td>A</td>
* <td><em>original event</em></td>
* </tr>
* <tr>
* <td>1</td>
* <td>B</td>
* <td><em>original event</em></td>
* </tr>
* <tr>
* <td>2</td>
* <td>X</td>
* <td><em>edit of sequence 0</em></td>
* </tr>
* </table>
*
* <p>
* The current value of the event with sequence number 0 is <code>X</code>.
*
* <p>
* If an original event has several edit events, the latest edit event (the one
* with the highest sequence number) determines its current value. Each edit
* event refers to an original event, never to another edit event.
*
* <p>
* Extending the example by appending a further edit event to the time series:
*
* <p>
* <table>
* <tr>
* <th>Sequence</th>
* <th>Value</th>
* <th>Type</th>
* <th></th>
* </tr>
* <tr>
* <td>3</td>
* <td>Y</td>
* <td><em>second edit of sequence 0</em></td>
* </tr>
* </table>
*
* <p>
* The current value of the event with sequence number 0 is now <code>Y</code>.
*
* <h3>Retained range</h3>
*
* <p>
* A time series topic retains a range of the most recent events. When a new
* event is added to the time series, older events that fall outside of the
* range are discarded. By default, this range includes the ten most recent
* events. A different range can be configured by setting the
* {@link TopicSpecification#TIME_SERIES_RETAINED_RANGE
* TIME_SERIES_RETAINED_RANGE} property.
*
*
* <h2>Subscribing to a time series topic</h2>
*
* <p>
* A session can {@link Session#subscribe subscribe} to a time series
* topic and
* {@link Session#addStream add a value stream} to receive updates about events appended to the time
* series. Events are represented by {@link Session.timeseries.Event} instances. Each event has a
* value and {@link Session.timeseries.EventMetadata metadata}. An edit event has two sets of
* metadata – its own metadata and that of the original event that it
* replaces.
*
* <h3>Subscription range</h3>
*
* <p>
* New subscribers are sent a range of events from the end of the time series.
* This is known as the <em>subscription range</em>. Configuring a subscription
* range is a convenient way to provide new subscribers with an appropriate
* subset of the latest events.
*
* <p>
* The default subscription range depends on whether the topic is configured to
* publish delta streams. If delta streams are enabled, new subscribers are sent
* the latest event if one exists. If delta streams are disabled, new
* subscribers are sent no events. Delta streams are enabled by default and can
* be disabled by setting the {@link TopicSpecification#PUBLISH_VALUES_ONLY
* PUBLISH_VALUES_ONLY} property to "true".
*
* <p>
* A larger subscription range can be configured by setting the
* {@link TopicSpecification#TIME_SERIES_SUBSCRIPTION_RANGE
* TIME_SERIES_SUBSCRIPTION_RANGE} property. Regardless of the
* <code>TIME_SERIES_SUBSCRIPTION_RANGE</code> property, if delta streams are
* enabled, new subscribers will be sent at least the latest event if one
* exists.
*
* <p>
* If the range of events is insufficient, the subscribing session can use a
* {@link Session.timeseries#rangeQuery range query} to retrieve older events.
*
* <p>
* When configuring a non-default subscription range for a time series topic,
* register value streams before subscribing to the topic. The session only
* maintains a local cache if the latest value received for a topic, not the
* full subscription range. If a value stream is added after a session has
* subscribed to a matching time series topic, the new stream will only be
* notified of the latest value.
*
* <h2>Updating a time series topic</h2>
*
* <p>
* A session can use {@link Session.timeseries#append append} to submit a value to be added to a
* time series. The server will add an event to the end of the time series based
* on the supplied value, with a new sequence number, timestamp, and the author
* set to the authenticated principal of the session.
*
* <p>
* A session can use {@link Session.timeseries#edit edit} to submit an edit to an original time
* series event, identified by its sequence number. The server will add an edit
* event to the end of the time series based on the supplied value, with a new
* sequence number, timestamp, and the author set to the authenticated principal
* of the session.
*
* <h2>Querying a time series topic</h2>
* <p>
* A {@link Session.timeseries.Query} is a configured query that can be evaluated for a time series
* topic using {@link Session.timeseries.Query#selectFrom selectFrom(topicPath)}. Results are
* provided as streams of {@link Event Event} instances.
* <p>
* {@link RangeQuery} is a builder for configuring a Query that selects a range
* of a time series. There are two types of range query that differ in how edits
* are processed – value range queries and edit range queries.
*
* <h3>Value range queries</h3>
*
* <p>
* A value range query returns a merged view of part of a time series. This is
* the most common time series query and appropriate for most applications.
*
* <p>
* The result of a value range query reflects the latest available edits and the
* {@link Session.timeseries.QueryResult#stream query result stream} is ordered by the original
* event sequence number, presenting edit events instead of the original events
* they replace. Original events that have no edit events are included verbatim.
* Original events that have edit events are replaced by the latest edit event.
*
* <p>
* A value range query of the example time series, with no range constraints so
* the entire time series is selected, returns two events:
*
* <pre>
* sequence=3, value=Y; original event sequence=0
* sequence=1, value=B
* </pre>
*
* <p>
* The original value of the first event is not provided. It's apparent that the
* first event is an edit event because it provides the metadata of the original
* event it replaces.
*
* <h3>Edit range queries</h3>
*
* <p>
* Applications with auditing and other administrative requirements can access
* original event values using an edit range query. An edit range query returns
* an unmerged view of a time series that can include both original events and
* the edit events that replace them. Edit range queries are rarely needed
* – value range queries satisfy most use cases.
*
* <p>
* Edit range queries provide a detailed view of a time series. Because this is
* potentially sensitive information, an edit range query can only be performed
* by a session that has the <code>QUERY_OBSOLETE_TIME_SERIES_EVENTS</code>
* permission for the target topic.
*
* <p>
* There are two sub-types of edit range query.
*
* <p>
* A full audit trail of edit events can be obtained using an <em>all edits</em>
* edit range query. The result contains all original events selected by the
* query, together with all subsequent edit events that affect the original
* events. The query result stream provides events in time series order. An all
* edits query of the example time series, with no range constraints so the
* entire time series is selected, returns four events:
*
* <pre>
* sequence=0; value=A
* sequence=1; value=B
* sequence=2; value=X; original event sequence=0
* sequence=3; value=Y; original event sequence=0
* </pre>
*
* <p>
* A <em>latest edits</em> edit range query returns a query result stream in
* time series order that contains all original events selected by the query,
* together with the latest edit events that affect the original events. A
* latest edits query of the example time series, with no range constraints so
* the entire time series is selected, returns three events:
*
* <pre>
* sequence=0; value=A
* sequence=1; value=B
* sequence=3; value=Y; original event sequence=0
* </pre>
*
* <p>
* The initial range of events delivered for a subscription to a time series
* topic is derived from a <em>latest edits</em> edit range query. See
* <em>Subscription Range</em>.
*
* <p>
* When evaluated for a time series that has no edit events, an edit range query
* will return the same results as a similarly configured value range query.
*
* <h2>Changes to a time series made outside the API</h2>
*
* <p>
* The API presents a time series as an append-only data structure of immutable
* events that is only changed by adding new events. The API does not allow
* events to be deleted or edited.
*
* <p>
* There are circumstances in which events can be removed from a time series by
* server operations outside the API. For example, a time series topic can be
* configured to discard or archive older events to save storage space; or the
* time series may be held in memory and lost if the server restarts. Subscribed
* sessions are not notified when events are removed in this way, but a session
* can infer the removal of events that are no longer included in query results.
* Similarly, an event's value can be changed on the server. For example, if an
* administrator changes its value to redact sensitive data. Again, subscribed
* sessions are not notified when events are modified, but a session can infer
* this has happened from query results.
*
* <p>
* Whether such changes can happen for a particular time series topic depends on
* the topic specification, and the administrative actions that are allowed. To
* write a robust application, do not rely on two Event instances with the same
* sequence number but obtained though different API calls, being equal; nor
* that there are no sequence number gaps between events in query results.
*
* <h2>Access control</h2>
* <p>
* The session must have the {@link TopicPermission#READ_TOPIC READ_TOPIC} topic
* permission for a topic to query a time series topic. The
* {@link Session.security.TopicPermission.QUERY_OBSOLETE_TIME_SERIES_EVENTS
* QUERY_OBSOLETE_TIME_SERIES_EVENTS} topic permission is additionally required
* to evaluate an {@link RangeQuery#forEdits edit range} query, or a
* {@link RangeQuery#forValues value range query} with an
* {@link RangeQuery#editRange edit range}.
* <p>
* The session must have the {@link Session.security.TopicPermission.UPDATE_TOPIC UPDATE_TOPIC}
* topic permission for a topic to {@link Session.timeseries#append append}
* a new event to a time series topic. The
* {@link Session.security.TopicPermission.EDIT_TIME_SERIES_EVENTS EDIT_TIME_SERIES_EVENTS} topic
* permission is additionally required to
* {@link Session.timeseries#edit submit an edit} to any time series event.
* The more restrictive {@link
* Session.security.TopicPermission.EDIT_OWN_TIME_SERIES_EVENTS
* EDIT_OWN_TIME_SERIES_EVENTS} topic permission allows a session to
* submit edits to time series topic events that are authored by the
* principal of the calling session.
*
* @namespace Session.timeseries
* @since 6.0
**/
module.exports = _interface('TimeSeries', [
/**
* Update a time series topic by appending a new value.
* <P>
* The server will add an event to the end of the time series based on the supplied value, with
* a new sequence number, timestamp, and the author set to the authenticated principal of the session.
*
* @param {String} topicPath - the path of the time series topic to update
* @param {Object} value - the event value
* @param {Function} [valueType] - the type of the supplied value. This must match the value type of the
* {@link diffusion.datatypes.DataType DataType} configured as the time series topic's
* {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE event value type}. By default will be inferred from the
* provided value.
* @return {Result<EventMetadata, ErrorReason>} a result that completes when a response is received from the
* server.
* @function Session.timeseries#append
*/
'append',
/**
* Update a time series topic by appending a new value that overrides the value of an existing event.
* <P>
* The existing event is identified by its sequence number and must be an original event.
* <P>
* The server will add an edit event to the end of the time series based on the supplied value, with a new sequence
* number, timestamp, and the author set to the authenticated principal of the session.
*
* @param {String} topicPath - the path of the time series topic to update
* @param {Number} originalSequence - the sequence number of the original event to edit
* @param {Object} value - the event value
* @param {Function} [valueType] - the type of the supplied value. This must match the value type of the
* {@link diffusion.datatypes.DataType DataType} configured as the time series topic's
* {@link TopicSpecification.TIME_SERIES_EVENT_VALUE_TYPE event value type}. By default will be inferred from the
* provided value.
*
* @return {Result<EventMetadata, ErrorReason>} a result that completes when a response is received from the server.
* @function Session.timeseries#edit
*/
'edit',
/**
* Return a default range query that performs a value range query of an entire time series.
* <P>
* Further queries with different parameters can be configured using the {@link RangeQuery}
* methods.
* <P>
* The result provides {@link diffusion.datatypes.Bytes} values, making it compatible with any event data type
* supported by time series topics. A query with a more specific value type can be configured using
* {@link RangeQuery#as}.
* <P>
* A RangeQuery equal to the one returned by this method can be created from an arbitrary RangeQuery as follows.
* <pre>
* defaults = anyRangeQuery.forValues()
* .fromStart()
* .untilLast(0)
* .limit(Number.MAX_INTEGER)
* .as(Buffer);
* </pre>
*
* @returns {RangeQuery} a RangeQuery with default settings
* @function Session.timeseries#rangeQuery
*/
'rangeQuery'
]);
/**
* Builder for queries that select a range of events from a time series.
*
* <p>
* See {@link Session.timeseries} for an overview of the various types of range
* query:
* <ul>
* <li>value range queries,
* <li>latest edits edit range queries, and
* <li>all edits edit range queries.
* </ul>
*
* <p>
* {@link Session.timeseries#rangeQuery} returns a default RangeQuery. Further
* queries with different parameters can be configured using the methods of
* this interface. {@link RangeQuery} instances are immutable. Each method
* returns a copy of this query with a modified setting. Method calls can be
* chained together in a fluent manner to create a query. For example:
*
* <pre>
* var defaultQuery = session.timeseries.rangeQuery();
*
* // A value range query that selects up to 100 original events from the
* // start of a time series.
* first100 = defaultQuery.forValues().fromStart().next(100);
* </pre>
*
* <h2>Creating value range queries</h2>
*
* <p>
* A value range query returns a merged view of part of a time series. This
* is the most common time series query and appropriate for most
* applications.
* <p>
* A value range query begins with the {@link RangeQuery#forValues} operator,
* followed by the <em>view range</em>. The view range determines the range
* of original events the time series that are of interest. See <em>Range
* expressions</em> below for the various ways to specify <code>RANGE</code>.
* <p>
* The events returned by the query are constrained by an optional <em>edit
* range</em>, introduced by the {@link RangeQuery#editRange()} operator. An event
* will only be included in the result if it is in the edit range. Let's
* consider some examples to see how the view range and the edit range
* interact.
*
* <table>
* <tr>
* <th>Query</th>
* <th>Meaning</th>
* </tr>
* <tr>
* <td><code>rangeQuery().forValues();</code></td>
* <td>For each original event in the time series, either return the latest
* edit event or if it has no edit events, return the original event.</td>
* </tr>
* <tr>
* <td><code>rangeQuery().forValues().from(100).to(150);</code></td>
* <td>For each original event with a sequence number between 100 and 150
* (inclusive), either return the latest edit event or if it has no edit
* events, return the original event.</td>
* </tr>
* <tr>
* <td>
* <code>rangeQuery().forValues().from(100).to(150).editRange().from(400);</code>
* </td>
* <td>For each original event with a sequence number between 100 and 150
* (inclusive), return the latest edit event with a sequence number greater
* than or equal to 400.
* <p>
* The result of this query will not include any original events because
* there is no overlap between the view range and the edit range.</td>
* </tr>
* </table>
*
* <p>
* Value range queries can be further refined using the {@link RangeQuery#limit limit()} and
* {@link RangeQuery#as as()} operators.
*
* <h2>Creating edit range queries</h2>
*
* <p>
* An edit range query returns an unmerged view of a time series than can
* include both original events and the edit events that replace them. Edit
* range queries are rarely needed – value range queries satisfy most
* use cases.
* <p>
* An edit range query begins with the {@link RangeQuery#forEdits()} operator,
* followed by the <em>view range</em>. The view range determines the range
* of original events the time series that are of interest. The result will
* only contain original events that are in the view range, and edit events
* for original events in the view range. See <em>Range expressions</em>
* below for the various ways to specify <code>RANGE</code>.
* <p>
* The events returned by the query are constrained by an optional <em>edit
* range</em>, introduced by the {@link RangeQuery#latestEdits()} or
* {@link RangeQuery#allEdits()} operators. An event will only be included in the
* result if it is in the edit range. Let's consider some example edit range
* queries.
*
* <table>
* <tr>
* <th>Query</th>
* <th>Meaning</th>
* </tr>
* <tr>
* <td><code>rangeQuery().forEdits();</code></td>
* <td>Return all events in a time series.</td>
* </tr>
* <tr>
* <td><code>rangeQuery().forEdits().from(100).to(150);</code></td>
* <td>Return the original events with a sequence number between 100 and 150
* (inclusive) and all edit events in the time series that refer to the
* original events.</td>
* </tr>
* <tr>
* <td><code>rangeQuery().forEdits().from(100).to(150).latestEdits();</code></td>
* <td>Return the original events with a sequence number between 100 and 150
* (inclusive) and the latest edit events in the time series that refer to
* the original events.</td>
* </tr>
* <tr>
* <td>
* <code>rangeQuery().forEdits().from(100).to(150).allEdits().from(400);</code>
* </td>
* <td>For each original event with a sequence number between 100 and 150,
* (inclusive) return all edit events with a sequence number greater than or
* equal to 400.
* <p>
* The result of this query will not include any original events because
* there is no overlap between the view range and the edit range.</td>
* </tr>
* </table>
*
* <p>
* Edit range queries can be further refined using the {@link RangeQuery#limit limit()} and
* {@link RangeQuery#as as()} operators.
*
* <h2>Range expressions</h2>
* <p>
* Range expressions are used to specify the view and edit ranges in value
* range and edit range queries. Each range expression has an
* <em>anchor</em> that determines where to start, and a <em>span</em> that
* determines where the range ends. Both anchor and span are
* <em>inclusive</em> – if an anchor or span falls on an event, the
* event is included in the result.
*
* <p>
* Both anchor and the span are optional. If the anchor is unspecified, the
* range begins at the start of the time series. If the span is unspecified,
* the range continues until the end of the time series.
*
* <h3>Anchors</h3>
*
* <p>
* There are five ways to specify an anchor.
* <table>
* <tr>
* <th>Anchor</th>
* <th>Meaning</th>
* </tr>
* <tr>
* <td>{@link RangeQuery#from from(Number)}</td>
* <td>Sets the anchor at an absolute sequence number.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#from from(Date)}</td>
* <td>Sets the anchor at an absolute time.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#fromStart fromStart}</td>
* <td>Sets the anchor at the start of the time series.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#fromLast fromLast(Number)}</td>
* <td>Sets the anchor at a relative offset before the end of the time
* series. For value range queries, <code>count</code> is the number of original
* events. For edit range queries, <code>count</code> is the number of events of
* any type.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#fromLast fromLast(Date}<br/>
* {@link RangeQuery#fromLastMillis fromLastMillis}</td>
* <td>Sets the anchor at a relative time before the timestamp of the last
* event of the time series.</td>
* </tr>
* </table>
* <p>
* An anchor point can be before the start or after the end of the time
* series.
*
* <h3>Spans</h3>
*
* <p>
* There are nine ways to specify a span.
* <table>
* <tr>
* <th>Span</th>
* <th>Meaning</th>
* </tr>
* <tr>
* <td>{@link RangeQuery#to to(Number)}</td>
* <td>The range ends at an absolute sequence number. The <code>sequence</code>
* argument may be before or after the anchor.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#toStart toStart}</td>
* <td>The range ends at the start of the time series.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#to to(Date)}</td>
* <td>The range ends at an absolute time. The <code>date</code> argument may
* be before or after the anchor.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#next next(Number)}</td>
* <td>The range ends at an event that is a relative number of events after
* the anchor. For value range queries, <code>count</code> is the number of
* original events. For edit range queries, <code>count</code> is the number of
* events of any type.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#next next(Date)}<br/>
* {@link RangeQuery#nextMillis nextMillis}</td>
* <td>The range ends at an event that is a relative time after the
* anchor.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#previous previous(Number)}</td>
* <td>The range ends at an event that is a relative number of events before
* the anchor. For value range queries, <code>count</code> is the number of
* original events. For edit range queries, <code>count</code> is the number of
* events of any type.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#previous previous(Date)}<br/>
* {@link RangeQuery#previousMillis previousMillis}</td>
* <td>The range ends at an event that is a relative time before the
* anchor.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#untilLast untilLast(Number}</td>
* <td>The range ends at an event that is a relative number of events before
* the end of the time series. For value range queries, <code>count</code> is the
* number of original events. For edit range queries, <code>count</code> is the
* number of events of any type.</td>
* </tr>
* <tr>
* <td>{@link RangeQuery#untilLast(Date)}<br/>
* {@link RangeQuery#untilLastMillis untilLastMillis}</td>
* <td>The range ends at an event that is a relative time before the
* timestamp of the last event of the time series.</td>
* </tr>
* </table>
* <p>
*
* <p>
* A span can specify an end point that is before the start or after the end
* of the time series.
* <p>
* If the span specifies an end point after the anchor, the range includes
* the first event at or following the anchor and ends at the last event at
* or preceding the end point. If the span specifies an end point before the
* anchor, the range includes the first event at or preceding the anchor and
* ends at the last event at or after the end point.
*
* <h2>Using the builder methods</h2>
*
* <p>
* Although the natural order of operators in a query is as shown in the
* syntax diagrams above, RangeQuery builder methods – those that
* return another RangeQuery – can be applied in any order with the
* following exceptions:
* <ul>
* <li>{@link RangeQuery#editRange} only applies to value range queries, so cannot
* follow <code>forEdits()</code> without an intervening <code>forValues();</code>
* <li>{@link RangeQuery#latestEdits} and {@link RangeQuery#allEdits} only apply
* to edit range queries, so cannot follow <code>forValues()</code> without an
* intervening <code>forEdits()</code>.
* </ul>
*
* <p>
* Each method overrides some configuration of the RangeQuery to which it is
* applied, as summarized in the following table.
*
* <p>
* <table>
* <tr>
* <th>Builder method</th>
* <th>Operator type</th>
* <th>Overridden configuration</th>
* </tr>
* <tr>
* <td><code>forValues()</code></td>
*
* <td>Value range</td>
* <td>Overrides the existing query type to create a new value range query.
* Overrides the existing view range with a new view range that selects the
* entire time series. The existing edit range is copied unchanged.</td>
* </tr>
* <tr>
* <td><code>forEdits()</code></td>
* <td>Value range</td>
* <td>Overrides the existing query type to create a new edit range query
* that includes all edits. Overrides the existing view range with a new
* view range that selects the entire time series. The existing edit range
* is copied unchanged.</td>
* </tr>
* <tr>
* <td><code>editRange()</code>
* <td>Edit range</td></td>
* <td>Overrides the existing edit range with a new edit range that selects
* the entire time series. The existing view range is copied unchanged.<br/>
* Throws <code>IllegalStateException</code> if this is not a value range
* query.</td>
* </tr>
* <tr>
* <td><code>latestEdits()</code><br/>
* <code>allEdits()</code></td>
* <td>Edit range</td>
* <td>Overrides the existing edit range with a new edit range that selects
* the entire time series. The existing view range is copied unchanged.
* <br/>
* Throws <code>Error</code> if this is not an edit range query.</td>
* </tr>
*
* <tr>
* <td><code>from()</code><br/>
* <code>fromStart()</code><br/>
* <code>fromLast()</code></td>
* <td>Anchor</td>
* <td>Overrides the anchor of the current range.</td>
* </tr>
*
* <tr>
* <td><code>to()</code><br/>
* <code>toStart()</code><br/>
* <code>next()</code><br/>
* <code>previous()</code><br/>
* <code>untilLast()</code></td>
* <td>Span</td>
* <td>Overrides the span of the current range.</td>
* </tr>
* <tr>
* <td><code>limit()</code></td>
* <td>Limit</td>
*
* <td>Overrides the limit.</td>
* </tr>
* <tr>
* <td><code>as()</code></td>
* <td>Query value type</td>
*
* <td>Overrides the query value type.</td>
* </tr>
* </table>
*
* @see Session.timeseries#rangeQuery
* @class RangeQuery
*/
module.exports.RangeQuery = _interface('RangeQuery', [
/**
* Return a copy of this RangeQuery configured to perform a value range query within the view range set to the
* entire time series.
* <P>
* <strong>Operator type:</strong> value range
*
* @return {RangeQuery} a copy of this range query configured to perform a view range query within a new view range
* that selects the time time series.
* @function RangeQuery#forValues
*/
'forValues',
/**
* Return a copy of this RangeQuery configured to perform an edit range query within the view range set to the
* entire time series.
* <p>
* <strong>Operator type:</strong> value range
*
* @return {RangeQuery} a copy of this range query configured to perform an edit range query with a new view range
* that selects the entire time series
* @function RangeQuery#forEdits
*/
'forEdits',
/**
* Return a copy of this RangeQuery configured to perform a value range query with the edit range set to the entire
* time series.
* <P>
* This operator can only be applied to value range queries. The default query returned by
* {@link Session.timeseries#rangeQuery rangeQuery()} is a value range query. The {@link RangeQuery#forValues}
* operator can be used to create a value range query from an edit range query.
* <P>
* <strong>Operator type:</strong> edit range
*
* @return {RangeQuery} a copy of this range query configured to perform a view range query with a new edit range
* that selects the entire time series
* @throws {Error} if this is not a value range query
* @function RangeQuery#editRange
*/
'editRange',
/**
* Return a copy of this RangeQuery configured to perform an edit range query with the edit range that selects all
* edits in the entire time series.
* <P>
* This operator can only be applied to edit range queries. The default query returned by
* {@link Session.timeseries#rangeQuery rangeQuery()} is a value range query. The {@link RangeQuery#forEdits}
* operator can be used to create an edit range query form a value range query.
* <P>
* <strong>Operator type:</strong> edit range
*
* @return {RangeQuery} a copy of this range query configured to perform an edit range query with a new edit range
* that selects all edits in the entire time series
* @throws {Error} if this is not an edit range query
* @function RangeQuery#allEdits
*/
'allEdits',
/**
* Return a copy of this RangeQuery configured to perform an edit range
* query with the edit range that selects latest edits in the entire
* time series.
*
* <p>
* This operator can only be applied to edit range queries. The default
* query returned by {@link Session.timeseries.#rangeQuery rangeQuery()} is a
* value range query. The {@link RangeQuery#forEdits()} operator can be used to
* create an edit range query from a value range query.
*
* <p>
* <strong>Operator type:</strong> edit range
* @return {RangeQuery} a copy of this range query configured to perform an edit range query with a new edit range
* that selects the latest edits in the entire time series
* @throws {Error} if this is not an edit range query
* @function RangeQuery#latestEdits
*/
'latestEdits',
/**
* Return a copy of this RangeQuery with the anchor of the current range
* configured to be either an absolute sequence number, or a Date instance.
*
* <p>
* <strong>Operator type:</strong> anchor
*
* @param {Number|Date} sequence - absolute sequence number or Date specifying the anchor of the returned range
* @return {RangeQuery} a copy of this range query with a new anchor
* @throws {Error} if sequence is negative
* @function RangeQuery#from
*/
'from',
/**
* Return a copy of this RangeQuery with the anchor of the current range
* configured to be the start of the time series.
*
* <p>
* There is a difference between <ode>fromStart(</code> and <code>from(0)</code>
* if the range also ends before the first event of the time series. For
* example, <code>fromStart().toStart()</code> is always empty, but
* <code>from(0).toStart()</code> includes the event with sequence number
* <code>0</code>.
*
* <p>
* <strong>Operator type:</strong> anchor
*
* @return {RangeQuery} a copy of this range query with a new anchor
* @function RangeQuery#fromStart
*/
'fromStart',
/**
* Return a copy of this RangeQuery with the anchor of the current range
* configured to be a relative offset before the end of the time series.
*
* <p>
* <strong>Operator type:</strong> anchor
*
* @param {Number} count - specifies the anchor as a number of events before the
* end of the time series. For value range queries, count is the
* number of original events. For edit range queries, count is
* the number of events of any type.
* @throws {Error} if count is negative
* @return {RangeQuery} a copy of this range query with a new anchor
* @function RangeQuery#fromLast
*/
'fromLast',
/**
* Return a copy of this RangeQuery with the anchor of the current range
* configured to be a relative time from the timestamp of the last event
* in the time series.
*
* <p>
* <strong>Operator type:</strong> anchor
*
* @param {Number} timeSpan - specifies anchor as a number of milliseconds relative
* to the timestamp of the latest event in the time series
* @throws {Error} if timeSpan is negative
* @return {RangeQuery} a copy of this range query with a new anchor
* @function RangeQuery#fromLastMillis
*/
'fromLastMillis',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to end at an absolute sequence number or Date instance.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number|Date} sequence - absolute sequence number or Date instance specifying the end of the
* returned range
* @throws {Error} if sequence is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#to
*/
'to',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to end at the start of the time series.
*
* <p>
* There is a difference between <code>toStart()</code> and <code>to(0)</code> if
* the range also starts before the first event of the time series. For
* example, <code>fromStart().toStart()</code> is always empty, but
* <code>fromStart().to(0)</code> includes the event with sequence number
* <code>0</code>.
*
* <p>
* <strong>Operator type:</strong> span
*
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#toStart
*/
'toStart',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to select a range of events following the anchor.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} count - specifies the end of the range of events to select
* following the anchor. For value range queries, count is the
* number of original events. For edit range queries, count is
* the number of events of any type.
* @throws {Error} if count is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#next
*/
'next',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to select a temporal range of events following the anchor.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} timeSpan - the time span in milliseconds of events following the
* anchor to select
* @throws {Error} if timeSpan is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#nextMillis
*/
'nextMillis',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to select a range of events preceding the anchor.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} count - specifies the end of the range of events to select
* preceding the anchor. For value range queries, count is the
* number of original events. For edit range queries, count is
* the number of events of any type.
* @throws {Error} if count is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#previous
*/
'previous',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to select a temporal range of events preceding the anchor.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} timeSpan - the time span in milliseconds of events preceding the
* anchor to select
* @throws {Error} if timeSpan is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#previousMillis
*/
'previousMillis',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to end a number of events before the end of the time
* series.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} count - specifies the end of the range of events to select as a
* number of events before the end of the time series. For value
* range queries, count is the number of original events. For
* edit range queries, count is the number of events of any type.
* @throws {Error} if count is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#untilLast
*/
'untilLast',
/**
* Return a copy of this RangeQuery with the span of the current range
* configured to end at a relative time from the timestamp of the last
* event in the time series.
*
* <p>
* <strong>Operator type:</strong> span
*
* @param {Number} timeSpan - specifies the end of the range of events to select as
* a number of milliseconds relative to the timestamp of the
* latest event in the time series
* @throws {Error} if timeSpan is negative
* @return {RangeQuery} a copy of this range query with a new span
* @function RangeQuery#untilLastMillis
*/
'untilLastMillis',
/**
* Return a copy of this RangeQuery that returns at most count events.
*
* <p>
* If the query would otherwise select more than count events, only the
* latest count values (those with the highest sequence numbers) are
* returned.
*
* <p>
* This is most useful when a temporal span has been configured with
* {@link RangeQuery#nextMillis} or {@link RangeQuery#previousMillis},
* where the potential number of returned events is unknown.
*
* <p>
* {@link QueryResult#isComplete()} can be used to determine whether a
* query has returned an incomplete result.
*
* <p>
* <strong>Operator type:</strong> limit
*
* @param {Number} count - the maximum number of events to return
* @throws {Error} if count is negative
* @return {RangeQuery} a copy of this range query with a new limit
* @function RangeQuery#limit
*/
'limit',
/**
* Return a copy of this RangeQuery with a different query value type.
*
* <p>
* A query can only be evaluated successfully against time series topics
* with a compatible event data type. If a query method is called for a
* time series topic with an incompatible event data type, the query
* will complete exceptionally.
*
* <p>
* If the event data type of the time series topic is known,
* compatibility of a particular <code>valueClass</code> can be checked using
* {@link diffusion.datatypes.DataType#canReadAs}. The
* {@link Session.timeseries#rangeQuery() default range query} has a query value
* type of {@link diffusion.datatypes.Bytes}, which is compatible with all time series value
* data types.
*
* <p>
* <strong>Operator type:</strong> query value type
*
* @return {RangeQuery} a copy of this range query with a new query value type
* @param {Function|DataType} valueClass - the value class or data type to read event values as
* @function RangeQuery#as
*/
'as',
/**
* Evaluate this query for a time series topic.
*
* <p>
* The session must have the <code>READ_TOPIC</code> topic permission for
* <code>topicPath</code> to evaluate a query. The
* <code>QUERY_OBSOLETE_TIME_SERIES_EVENTS</code> topic permission is also
* required if this is an {@link RangeQuery#forEdits edit range} query,
* or a {@link RangeQuery#forValues value range query} with an
* {@link RangeQuery#editRange edit range}.
*
* @param {String} topicPath - the path of the time series topic to query
*
* @return {Result<QueryResult, ErrorReason>} a result that completes when a response is
* received from the server.
* <p>
* If the query returned results, the result will
* complete successfully and provide an {@link QueryResult}.
* <p>
* Otherwise, the result will complete exceptionally
* with an {@link ErrorReason}.
*
* @function RangeQuery#selectFrom
*/
'selectFrom'
]);
/**
* Time series event metadata.
*
* @class EventMetadata
* @property {Number} sequence - Sequence number identifying this event within its time series.
* Assigned by the server when the event is created.
*
* <P>
* Sequence numbers are unique within a time series. Each event appended
* to a time series is assigned a sequence number that is is equal to
* the sequence number of the preceding event plus one.
* @property {Number} timestamp - Event timestamp. Assigned by the server when the event is created.
*
* <p>
* Events do not have unique timestamps. Events with different sequence
* numbers may have the same timestamp.
*
* <p>
* Subsequent events in a time series usually have timestamps that are
* greater or equal to the timestamps of earlier events, but this is not
* guaranteed due to changes to the time source used by the server.
*
* Timestamps represent the difference, measured in milliseconds, between
* the time the server added the event to the time series and midnight,
* January 1, 1970 UTC
* @property {String} author - Server-authenticated identity of the session that created the event.
* <P>
* If the session that created the event was not authenticated, the author
* will be an empty string.
*/
module.exports.EventMetadata = _interface('EventMetadata', [
'sequence',
'timestamp',
'author'
]);
/**
* An event in a time series.
* <P>
* Two instances are {@link Event#equals equal} if and only if they have identical
* attributes. Typically, two Event instances that have the same sequence number will
* be equal, but this may not be true if the event has changed on the server –
* see <em>Changes to a time series made outside the API</em> in the
* {@link Session.timeseries TimeSeries} documentation.
*
* @class Event
* @augments EventMetadata
*/
module.exports.Event = _interface('Event', [
/**
* The value associated with the event.
*
* @property {Object} value
*/
'value',
/**
* If this is an edit event, returns the metadata of the original event that this
* event replaces; otherwise returns this event.
* <P>
* The result is always the metadata of an original event, never that of an edit event.
*
* @property {EventMetadata} originalEvent
*/
'originalEvent',
/**
* Return whether this is an edit event.
* <P>
* <code>x.isEditEvent</code> is equivalent to <code>x.originalEvent != x</code>.
*
* @property {Boolean} isEditEvent
*/
'isEditEvent'
]);
/**
*
* Query result providing a {@link Stream} of events.
*
* @class QueryResult
*/
module.exports.QueryResult = _interface('QueryResult', [
/**
* Returns the number of events selected by the query.
*
* <p>
* This number may be greater than <code>stream().count()</code> due to a
* policy of the time series topic to limit the number of returned
* results, or the use of {@link RangeQuery#limit}.
*
* @property {Number}selectedCount
*/
'selectedCount',
/**
* Provides a stream from which to consume events.
*
* @return {Stream} the events.
* @function QueryResult#stream
*/
'stream',
/**
* Returns whether this result includes all events selected by the
* query.
*
* @property {Boolean} isComplete
*/
'isComplete',
/**
* Returns a description of the structure of the result stream.
*
* @property {StreamStructure} a StreamStructure that describes the structure of the result stream
*/
'streamStructure',
/**
* Merge this result with <code>other</code>, combining original events and
* edit events, to produce an {@link QueryResult} of type
* {@link StreamStructure#VALUE_EVENT_STREAM VALUE_EVENT_STREAM}
*
* <p>
* The following rules are applied to calculate the result:
* <ul>
* <li>If this result and <code>other</code> have an event with equal
* sequence numbers, the event from <code>other</code> is selected.
* <li>An edit event is selected in place of its original event.
* <li>If there are multiple edit events of an original edit, the one
* with the highest sequence is selected.
* </ul>
*
* <p>
* The returned result implements {@link QueryResult#isComplete()} to return true
* and {@link QueryResult#selectedCount()} to return the count of events in the
* stream, regardless of whether this result is complete.
*
* @param {QueryResult} other - the other query result to merge
* @return {QueryResult} the merged result
*
* @function QueryResult#merge
*/
'merge'
]);