public interface TopicUpdate extends Feature
Topics can be set to new values using stateless
set
operations or an
UpdateStream
. Both ensure that new values are applied
safely to appropriate topics.
Additionally, JSON topics can be updated with a
JSON Patch
. A patch is a list of operations that
modifies a JSON value, removing the need to supply a complete new value. This
is useful if the source of the updates doesn't provide values. For one-off,
small changes to large JSON values, it can be significantly cheaper to apply
a patch than to use set
to provide the complete value.
An update stream is created for a specific topic. The type of the topic must match the type of values passed to the update stream. An update stream can be used to send any number of updates. It sends a sequence of updates for a specific topic to the server. If supported by the data type, updates will be sent to the server as a stream of binary deltas.
Update streams have additional ways of failing compared to stateless set operations but when used repeatedly have lower overheads. This is because update streams maintain a small amount of state that reduces the overhead of operations but can become invalid for example, if the topic is deleted, or some other session updates the topic value.
By default, update streams use a form of optimistic locking. An update
stream can update its topic incrementally as long as nothing else updates
the topic. If the topic is updated independently (for example, by another
session, or by the current session via set or a different update stream),
then the next update performed by the update stream will result in an
InvalidUpdateStreamException
.
Applications can chose to use collaborative locking to coordinate exclusive
access to a topic. To follow this pattern acquire a
session lock
, and use it with a
lock constraint
.
The application is responsible for designing a locking scheme which
determines which lock is required to access a particular topic, and for
ensuring that all parts of the application that update the topic follow this
scheme. Lock constraints and an application locking scheme can also ensure a
sequence of set operations has exclusive access to the topic.
Constraints can be applied to the setting of a value and creation of an update stream. Constraints describe a condition that must be satisfied for the operation to succeed. The constraints are evaluated on the server. The available constraints: are an active session lock, the absence of a topic, the current value of the topic being updated, and a part of the current value of the topic being updated.
When a string
, int64
, or
double
topic is set to null
, the topic will
be updated to have no value. If a previous value was present subscribers will
receive a notification that the new value is null
. New subscribers
will not receive a value notification. Attempting to set any other type of
topic to null
will cause a NullPointerException
to be thrown.
When setting a value using either stateless operations or update streams it
is possible to add a topic if one is not present. This is done using the
addAndSet
methods or providing a topic specification when creating the update stream.
If a topic exists these methods will update the existing topic.
All methods provided by this feature are compatible with time series topics
except for applyJsonPatch(String, String)
. The TimeSeries
feature can be used to update time series topics with custom metadata and
provides query capabilities.
To update a topic a session needs
UPDATE_TOPIC
permission for the topic path. To create a topic a session
needs
MODIFY_TOPIC
permission for the topic path. Requests that combine adding a
topic and setting the value such as
addAndSet
require both permissions.
This feature may be obtained from a session
as follows:
TopicUpdate topicUpdate = session.feature(TopicUpdate.class);
This feature is also extended by the topics feature
. This
means is it possible to use the methods described here through the
topics feature
.
Modifier and Type | Interface and Description |
---|---|
static class |
TopicUpdate.FailedPatchException
Exception thrown to report that applying a JSON Patch failed.
|
static class |
TopicUpdate.InvalidPatchException
Exception thrown to report that a JSON Patch was invalid.
|
static interface |
TopicUpdate.JsonPatchResult
|
Modifier and Type | Method and Description |
---|---|
<T> CompletableFuture<TopicCreationResult> |
addAndSet(String path,
TopicSpecification specification,
Class<T> valueClass,
T value)
Ensures a topic exists and sets its value.
|
<T> CompletableFuture<TopicCreationResult> |
addAndSet(String path,
TopicSpecification specification,
Class<T> valueClass,
T value,
UpdateConstraint constraint)
Ensures a topic exists and sets its value.
|
CompletableFuture<TopicUpdate.JsonPatchResult> |
applyJsonPatch(String path,
String patch)
Applies a JSON Patch to a JSON topic.
|
CompletableFuture<TopicUpdate.JsonPatchResult> |
applyJsonPatch(String path,
String patch,
UpdateConstraint constraint)
Applies a JSON Patch to a JSON topic.
|
<T> UpdateStream<T> |
createUpdateStream(String path,
Class<T> valueClass)
Creates an
update stream to use for updating a
specific topic. |
<T> UpdateStream<T> |
createUpdateStream(String path,
Class<T> valueClass,
UpdateConstraint constraint)
Creates an
update stream to use for updating a
specific topic. |
<T> UpdateStream<T> |
createUpdateStream(String path,
TopicSpecification specification,
Class<T> valueClass)
Creates an
update stream to use for creating and
updating a specific topic. |
<T> UpdateStream<T> |
createUpdateStream(String path,
TopicSpecification specification,
Class<T> valueClass,
UpdateConstraint constraint)
Creates an
update stream to use for creating and
updating a specific topic. |
<T> CompletableFuture<?> |
set(String path,
Class<T> valueClass,
T value)
Sets the topic to a specified value.
|
<T> CompletableFuture<?> |
set(String path,
Class<T> valueClass,
T value,
UpdateConstraint constraint)
Sets the topic to a specified value.
|
getSession
<T> CompletableFuture<?> set(String path, Class<T> valueClass, T value)
The null
value can only be passed to the value
parameter
when updating string
, int64
, or double
topics.
When a string
, int64
,
or double
topic is set to null
, the
topic will be updated to have no value. If a previous value was present
subscribers will receive a notification that the new value is
null
. New subscribers will not receive a value notification.
T
- the type of the valuepath
- the path of the topicvalueClass
- the type of the valuevalue
- the value. String
,
int64
, and
double
topics accept
null
, as described above. Using null
with
other topic types is an error and will throw a
NullPointerException
.
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include:
NoSuchTopicException
– if there is no topic
bound to path
;
IncompatibleTopicException
– if updates
cannot be applied to the topic, for example if a topic view has
bound a reference topic to the path;
IncompatibleTopicStateException
– if the topic
is managed by a component (such as fan-out) that prohibits
updates from the caller;
ClusterRoutingException
– if the operation failed
due to a transient cluster error;
PermissionsException
– if the calling
session does not have the
UPDATE_TOPIC
permission for path
;
SessionClosedException
– if the session is
closed.
<T> CompletableFuture<?> set(String path, Class<T> valueClass, T value, UpdateConstraint constraint)
Takes a constraint that must be satisfied for the update to be applied.
In other respects this method works in the same way as
set(String, Class, Object)
.
T
- the type of the valuepath
- the path of the topicvalueClass
- the type of the valuevalue
- the value. String
,
int64
, and
double
topics accept
null
, as described above. Using null
with
other topic types is an error and will throw a
NullPointerException
.constraint
- the constraint that must be satisfied for the topic
to be updated
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include:
NoSuchTopicException
– if there is no topic
bound to path
;
IncompatibleTopicException
– if updates
cannot be applied to the topic, for example if a topic view has
bound a reference topic to the path;
UnsatisfiedConstraintException
– if the
constraint
is not satisfied by the topic bound to
path
;
IncompatibleTopicStateException
– if the topic
is managed by a component (such as fan-out) that prohibits
updates from the caller;
ClusterRoutingException
– if the operation failed
due to a transient cluster error;
PermissionsException
– if the calling
session does not have the
UPDATE_TOPIC
permission for path
;
SessionClosedException
– if the session is
closed.
<T> CompletableFuture<TopicCreationResult> addAndSet(String path, TopicSpecification specification, Class<T> valueClass, T value)
If a topic does not exist at the path
, one will be created using
the specification
. If a topic does exist, its specification must
match specification
, otherwise the operation will fail with
IncompatibleTopicException
.
In other respects this method works in the same way as
set(String, Class, Object)
.
T
- the type of the valuepath
- the path of the topicspecification
- the required specification of the topicvalueClass
- the type of the valuevalue
- the value. String
,
int64
, and
double
topics accept
null
, as described above. Using null
with
other topic types is an error and will throw a
NullPointerException
.
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include those
reported by set
except
NoSuchTopicException
as well as:
TopicControl.InvalidTopicPathException
– path
is not a valid topic path;
TopicControl.InvalidTopicSpecificationException
– the
specification is invalid, possibly because mandatory properties
not supplied;
TopicControl.TopicLicenseLimitException
– the
topic could not be added as it would breach a licensing limit;
PermissionsException
– if the calling
session does not have the
MODIFY_TOPIC
and the
UPDATE_TOPIC
permissions for path
;
IllegalArgumentException
- if the type of the specification does
not match the type of the update<T> CompletableFuture<TopicCreationResult> addAndSet(String path, TopicSpecification specification, Class<T> valueClass, T value, UpdateConstraint constraint)
If a topic does not exist at the path
, one will be created using
the specification
. If a topic does exist, its specification must
match specification
, otherwise the operation will fail with
IncompatibleTopicException
.
Takes a constraint that must be satisfied for the topic to be created or the update to be applied.
In other respects this method works in the same way as
set(String, Class, Object)
.
T
- the type of the valuepath
- the path of the topicspecification
- the required specification of the topicvalueClass
- the type of the valuevalue
- the value. String
,
int64
, and
double
topics accept
null
, as described above. Using null
with
other topic types is an error and will throw a
NullPointerException
.constraint
- the constraint that must be satisfied for the topic
to be updated
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include those
reported by set
except NoSuchTopicException
as well as:
TopicControl.InvalidTopicPathException
– path
is not a valid topic path;
TopicControl.InvalidTopicSpecificationException
– the
specification is invalid, possibly because mandatory properties
not supplied;
TopicControl.TopicLicenseLimitException
– the
topic could not be added as it would breach a licensing limit;
PermissionsException
– if the calling
session does not have the
MODIFY_TOPIC
and the
UPDATE_TOPIC
permissions for path
;
IllegalArgumentException
- if the type of the specification does
not match the type of the update<T> UpdateStream<T> createUpdateStream(String path, Class<T> valueClass)
update stream
to use for updating a
specific topic.
The type of the topic being updated must match the type derived from the
valueClass
parameter.
Update streams send a sequence of updates for a specific topic. The
updates may be delivered to the server as binary deltas. They do not
provide exclusive access to the topic. If exclusive access is required
update streams should be used with
session locks
as constraints.
Streams are validated lazily when the first UpdateStream.set(T)
or
UpdateStream.validate()
operation is completed. Once validated a
stream can be invalidated, after which it rejects future
updates.
T
- type of the values expected by the update streampath
- the path of the topicvalueClass
- the type of the values expected by the update stream<T> UpdateStream<T> createUpdateStream(String path, Class<T> valueClass, UpdateConstraint constraint)
update stream
to use for updating a
specific topic.
Takes a constraint that must be satisfied for the update stream to be validated.
In other respects this method works in the same way as
createUpdateStream(String, Class)
.
T
- type of the values expected by the update streampath
- the path of the topicvalueClass
- the type of the values expected by the update streamconstraint
- the constraint that must be satisfied for the update
stream to be validated<T> UpdateStream<T> createUpdateStream(String path, TopicSpecification specification, Class<T> valueClass)
update stream
to use for creating and
updating a specific topic.
If a topic does not exist at the path
one will be created using
the specification
when the update stream is validated. If a
topic does exist, its specification must match specification
,
otherwise the operation will fail with
IncompatibleTopicException
.
In other respects this method works in the same way as
createUpdateStream(String, Class)
.
T
- type of the values expected by the update streampath
- the path of the topicspecification
- the required specification of the topicvalueClass
- the type of the values expected by the update streamIllegalArgumentException
- if the topic type of the specification
does not match the type of values<T> UpdateStream<T> createUpdateStream(String path, TopicSpecification specification, Class<T> valueClass, UpdateConstraint constraint)
update stream
to use for creating and
updating a specific topic.
If a topic does not exist at the path
one will be created using
the specification
when the update stream is validated. If a
topic does exist, its specification must match specification
,
otherwise the operation will fail with
IncompatibleTopicException
.
Takes a constraint that must be satisfied for the update stream to be validated.
In other respects this method works in the same way as
createUpdateStream(String, Class)
.
T
- type of the values expected by the update streampath
- the path of the topicspecification
- the required specification of the topicvalueClass
- the type of the values expected by the update streamconstraint
- the constraint that must be satisfied for the update
stream to be validatedIllegalArgumentException
- if the topic type of the specification
does not match the type of valuesCompletableFuture<TopicUpdate.JsonPatchResult> applyJsonPatch(String path, String patch)
The patch
argument should be formatted according to the JSON
Patch standard (RFC 6902).
Patches are a sequence of JSON Patch operations contained in an array. They are applied as an atomic update to the previous value if the resulting update is successfully calculated. The following patch will check the value at a specific key and update if the expected value is correct:
[{"op":"test", "path":"/price", "value" : 22}, {"op":"add", "path":"/price", "value": 23}]
The available operations are:
{"op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ]}
{"op": "remove", "path": "/a/b/c"}
{"op": "replace", "path": "/a/b/c", "value": 43}
{"op": "move", "from": "/a/b/c", "path": "/a/b/d"}
{"op": "copy", "from": "/a/b/c", "path": "/a/b/e"}
{"op": "test", "path": "/a/b/c", "value": "foo"}
The test operation checks that the CBOR representation of the value of a
topic is identical to the value provided in the patch after converting it
to CBOR. If the value is represented differently as CBOR, commonly due to
different key ordering, then the patch will return the index of the
failed operation . e.g the values
{"foo": "bar", "count": 43}
and
{"count": 43, "foo": "bar"}
are unequal despite semantic equality
due to the differences in a byte for byte comparison.
path
- the path of the topic to patchpatch
- the JSON Patch
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include:
TopicUpdate.InvalidPatchException
– if the patch is not a
valid JSON Patch;
TopicUpdate.FailedPatchException
– if applying the patch
fails, this will occur if the topic's present value is invalid
CBOR (see TopicSpecification.VALIDATE_VALUES
);
NoSuchTopicException
– if there is no topic
bound to path
;
IncompatibleTopicException
– if patch cannot
be applied to the topic, for example if the topic type is not
JSON
.
IncompatibleTopicStateException
– if the topic
is managed by a component (such as fan-out) that prohibits
updates from the caller;
ClusterRoutingException
– if the operation failed
due to a transient cluster error;
PermissionsException
– if the calling
session does not have the
UPDATE_TOPIC
permission for path
;
SessionClosedException
– if the session is
closed.
CompletableFuture<TopicUpdate.JsonPatchResult> applyJsonPatch(String path, String patch, UpdateConstraint constraint)
Takes a constraint that must be satisfied for the update to be applied.
In other respects this method works in the same way as
applyJsonPatch(String, String)
.
path
- the path of the topic to patchpatch
- the JSON Patchconstraint
- the constraint that must be satisfied for the patch to
be applied
If the task fails, the CompletableFuture will complete
exceptionally with a CompletionException
. Common reasons
for failure, listed by the exception reported as the
cause
, include:
TopicUpdate.InvalidPatchException
– if the patch is not a
valid JSON patch;
TopicUpdate.FailedPatchException
– if applying the patch
fails, this will occur if the topic's present value is invalid
CBOR (see TopicSpecification.VALIDATE_VALUES
);
NoSuchTopicException
– if there is no topic
bound to path
;
IncompatibleTopicException
– if patch cannot
be applied to the topic, for example if the topic type is not
JSON
.
IncompatibleTopicStateException
– if the topic
is managed by a component (such as fan-out) that prohibits
updates from the caller;
ClusterRoutingException
– if the operation failed
due to a transient cluster error;
PermissionsException
– if the calling
session does not have the
UPDATE_TOPIC
permission for path
;
SessionClosedException
– if the session is
closed.
Copyright © 2022 Push Technology Ltd. All Rights Reserved.