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. An UpdateStreamBuilder can
be obtained using UpdateStream.Builder
. 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.
When supplying values to an update the value type must be specified
(valueClass parameter). When using update streams, the value type is
specified when creating the stream. The class specified will depend upon the
TopicType
of the topic being updated, according to the supported
types for the corresponding DataType
. For example, for a
JSON
topic, a type of JSON.class
should
be supplied.
Note that for BINARY
topics the value class can be
Binary.class
or Bytes.class
(or any subtype of
these) but the value must be effectively immutable. This means that any array
backing the supplied value must not be changed otherwise immutability would
be violated and results could be unpredictable.
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)
Deprecated.
since 6.9
|
<T> UpdateStream<T> |
createUpdateStream(String path,
Class<T> valueClass,
UpdateConstraint constraint)
Deprecated.
since 6.9
|
<T> UpdateStream<T> |
createUpdateStream(String path,
TopicSpecification specification,
Class<T> valueClass)
Deprecated.
since 6.9
|
<T> UpdateStream<T> |
createUpdateStream(String path,
TopicSpecification specification,
Class<T> valueClass,
UpdateConstraint constraint)
Deprecated.
since 6.9
|
UpdateStream.Builder |
newUpdateStreamBuilder()
Creates an update stream builder to use for creating update streams.
|
<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 appropriate permissions for path
; in
general the calling session must have the
MODIFY_TOPIC
and
UPDATE_TOPIC
permissions, but if the topic exists and has the
same specification then it's sufficient for the calling session's
principal to be the topic owner
.
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@Deprecated <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@Deprecated <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@Deprecated <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@Deprecated <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 valuesUpdateStream.Builder newUpdateStreamBuilder()
CompletableFuture<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 © 2024 DiffusionData Ltd. All Rights Reserved.