UNPKG

diffusion

Version:

Diffusion JavaScript client

1,249 lines (1,213 loc) 48.3 kB
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 &ndash; 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 &ndash; 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 &ndash; 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 * &ndash; 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 &ndash; 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> &ndash; 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 &ndash; those that * return another RangeQuery &ndash; 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 &ndash; * 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' ]);