Interface SynchronizedStateProvider<P,F>
-
- Type Parameters:
P
- the object expected in the case of partial synchronizationF
- the object expected in the case of full synchronization.
- All Known Implementing Classes:
AbstractSynchronizedStateProvider
,DelegatingRoleAwareSynchronizedStateProvider
public interface SynchronizedStateProvider<P,F>
This is a provider for a subsystem that wishes to synchronize data across redundancy. There are two possibilities: one way, where data is only synchronized from master to backup, or bi-directional, in which data is synchronized both ways.
These are typically registered on subsystem setup, and thus handle the gateway role internally (that is, they don't get re-registered on change to role, if a gateway goes independent->master, or similar). If the role changes, however, the system will call shutdown and then init again.
This provider packs functions for uni-directional and bi-direction together. If uni-directional, the PULL functions will never be called on the backup, and the apply functions will never be called on the master.
One of the design goals of the sync system is that the implementation doesn't need to worry about sync logic too much, or node role. In practice, most implementations do care whether or not they're master for various reason. TheAbstractSynchronizedStateProvider
provides some useful helper functions, including isMaster().
The sync methodology operates around the VersionToken. This is "version" comprising of a string id (usually a uuid) for "major", and then a long revision based on that. The token can also include arbitrary data, though, so there are a range of sync methodologies that can be employed:
Basic Strategy:
The basic strategy is to try to get the backup's version to match. Start with null version on the backup, and a new version on the master. Upon apply, set the current version to what was reported in the state.
This strategy can be adapted for bi-directional, except in that case, you will also modify the revision on the backup. As a result, it is advised to set the current version to max(state.version, current.version)+1 on the backup after applying, and then immediately request sync. The master will then perform a pull with the last revision that it saw from the backup.
Custom One-Way Strategy:
Set the version id to something that is known on both sides, set the master revision to 1, and the backup to 0. Put an object with more information in the custom field of the version token. The backup will always try to do a partial pull, but the master is free to return an empty State if no changes have actually occurred.
Note that sync attempts happen as a result of requestSync, so data is not sent between gateways if neither side is requesting a sync.
Sync Cycle- Upon connection, the backup will always call synchronize on the backup first, which means the backup will receive a manifest of all current provider versions. It will generate a list of sync operations to perform, based on reported current versions.
- The backup will execute and apply those requests.
- If any providers have requested sync, the backup will call synchronize on the master- in turn causing the master to generate pull requests.
- After this initial cycle, either side may call requestSync at any point, and synchronization attempts will occur.
-
-
Method Summary
All Methods Instance Methods Abstract Methods Default Methods Modifier and Type Method Description default void
appendMetrics(java.util.List<MetricValue> metrics)
void
applyFullState(State<F> state)
Applies the full state.void
applyPartialState(State<P> state)
Should apply the partial state.default boolean
fullRequiresRestart()
This is used by the system to detect "major" changes.java.lang.String
getId()
A simple and unique identifier for this state subsystem.VersionToken
getVersion()
This represents the current version of the state.void
init(SyncController controller)
"Starts" the provider.boolean
isBidirectional()
Indicates the state can be synchronized bi-directionally.State<F>
pullFull()
Should return the full state.State<P>
pullPartial(VersionToken version)
Should return a set of partial changes going from the provided version.void
shutdown()
Called when the system is being shut down or the gateway has changed role.
-
-
-
Method Detail
-
init
void init(SyncController controller)
"Starts" the provider. The controller can be used to request sync whenever the provider thinks there has been a change. It can be called freely, the parent system will coalesce calls into single operations that happen periodically.
-
shutdown
void shutdown()
Called when the system is being shut down or the gateway has changed role. It should be expected that startup may be called again on the same instance.
-
getId
java.lang.String getId()
A simple and unique identifier for this state subsystem.
-
isBidirectional
boolean isBidirectional()
Indicates the state can be synchronized bi-directionally.
-
fullRequiresRestart
default boolean fullRequiresRestart()
This is used by the system to detect "major" changes. When this is true, and a full sync is required, the system is marked as "Out of Date", and knows it will be restarted when an update arrives.
-
getVersion
VersionToken getVersion()
This represents the current version of the state. It is a *little* tricky, however, when it comes to bi-directional states. Bi-directional states mean that changes can happen on both sides and are merged when synchronized. How this works: 1) Utimately the goal is to have the version be the same on both sides. 2) The state synchronizer will keep track of the last version seen, both locally and remotely. 3) When a partial state is applied here, this provider determines if it still has changes. If so, it requests a sync. 4) When the partial pull comes in, it will be for an older revision- this revision is relative to this side. At this point, the provider returns the outstanding changes with an id equal to what was last received. If in the mean time the other side has modified the state again, it the cycle would continue- except in step 3 there shouldn't be any more outstanding changes. This logic is handled by the AbstractSynchronizedStateProvider.
-
pullPartial
State<P> pullPartial(VersionToken version)
Should return a set of partial changes going from the provided version. If not available, should return State.outOfDate().
-
applyPartialState
void applyPartialState(State<P> state)
Should apply the partial state. If the process fails for some reason, the system should reset its internal version and request sync, so that the full state may be transferred.
-
applyFullState
void applyFullState(State<F> state)
Applies the full state. If the update fails, the system should reset its internal version and request sync in order to retry.
-
appendMetrics
default void appendMetrics(java.util.List<MetricValue> metrics)
-
-