You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An all-too-common challenge among plugins looking to support external data sources is the unfortunate need to resolve the consequences of sharing a resource between threads. The Bukkit API's affinity for the main thread provides a very convenient way for us to predict how most resources will be shared--if code is called on the main thread, it will always be called in sequence, never concurrently.
This convenience comes with a price--if something takes too long, it can't be done on the main thread without blocking everything else and effectively stalling the server. Originally, Clans loads everything from files at the start so that things don't take too long--but what if files, preloading are not an option? If we update data, how do we know when it's been fully applied? This is where asynchrony must come into play.
Feature
Elements of Clans and its API currently access data in a blocking fashion with certain guarantees:
All data is loaded at startup
We know about and direct all data updates
Data is written to cache; the saving is handled at shutdown
Data written to the cache is applied instantly, allowing us to make assumptions as to the state of the cache based on the order of task executions
All of these points (and particularly the last one) must be addressed by any new non-blocking API.
Design considerations:
We can still preload. All code in getter hot-paths must be cached values with an acceptable time-to-live.
For writes we must snapshot and validate state during all updates so that business logic can (and must) anticipate conditions of invalid state.
The cache must be managed internally. Writes will propagate to the cache on success. Writing and saving are combined.
No assumptions about the state of the cache can be made. Each write operation will obtain a lock on its particular resource and support optionally maintaining this lock until dependent business logic has completed its tasks.
The text was updated successfully, but these errors were encountered:
The new API separates reads and writes, requiring a context switch to access write functionality. The idea with these write layers is that the updates that they accept will not immediately write through to the data source. Additionally, the write layer will allow the expected original state of the clan data to be validated as a prerequisite to a write being applied.
Write layer methods (abstract)
isApplied - boolean
addPrecondition - Predicate<Data>
apply - CompletableFuture<Void>
Can complete exceptionally with appropriate error. Always sets isApplied = true.
cancel
Prevents the application of this write object (such as if this write layer is first passed to an Event before apply is called). Throws if isApplied = true.
copy - MutableData
Creates a deep copy with isApplied, preconditions reset and cancel removed.
Implementation hints
cancel can be implemented as adding a Predicate with a _ -> false contract
a separate queue should be maintained for operation-sourced predicates. this simplifies the copy operation while maintaining the original semantics of the write layer's creation.
// operation-sourced predicate exampleWritew = clan.asMutable();
w.addPower(3.0d);
// This automatically adds the following predicate, internally, like sow.osp.add(data -> data.getPower() != w.power);
// Only after this is w.power updated
Abstract
An all-too-common challenge among plugins looking to support external data sources is the unfortunate need to resolve the consequences of sharing a resource between threads. The Bukkit API's affinity for the main thread provides a very convenient way for us to predict how most resources will be shared--if code is called on the main thread, it will always be called in sequence, never concurrently.
This convenience comes with a price--if something takes too long, it can't be done on the main thread without blocking everything else and effectively stalling the server. Originally, Clans loads everything from files at the start so that things don't take too long--but what if files, preloading are not an option? If we update data, how do we know when it's been fully applied? This is where asynchrony must come into play.
Feature
Elements of Clans and its API currently access data in a blocking fashion with certain guarantees:
All of these points (and particularly the last one) must be addressed by any new non-blocking API.
Design considerations:
The text was updated successfully, but these errors were encountered: