Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

import java.util.UUID;

/**
* Base class for event handlers that can be registered with {@link Octopus}.
*/
@AllArgsConstructor
@Getter
public abstract class EventHandler {
Expand Down
109 changes: 75 additions & 34 deletions api/src/main/java/studio/o7/octopus/plugin/api/Octopus.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,44 @@

import java.util.UUID;

/**
* Main entry point for interacting with Octopus.
*
* <p>
* Octopus provides operations to publish ("call") objects to a key, retrieve entries, and
* subscribe listeners to key patterns.
* </p>
*
* <p><b>Key format</b></p>
* <ul>
* <li>Keys are dot-separated tokens, e.g. {@code foo.bar.baz}.</li>
* <li>Patterns may include wildcards (see subscription methods / {@link EventHandler}).</li>
* </ul>
*
* <p><b>Wildcard patterns</b></p>
* <ul>
* <li>{@code *} matches exactly one token (between dots).</li>
* <li>{@code &gt;} matches zero or more tokens until the end of the key.</li>
* </ul>
*
* <p>
* Example: {@code foo.*.bar} matches {@code foo.x.bar} but not {@code foo.x.y.bar}.<br>
* Example: {@code foo.&gt;} matches {@code foo}, {@code foo.bar}, {@code foo.bar.baz}, etc.
* </p>
*/

public interface Octopus {

/**
* Returns the active {@link Octopus} implementation.
*
* <p>
* The returned instance is the entry point for calling objects, retrieving entries,
* and registering listeners.
* </p>
*
* @return the active {@link Octopus} instance
*/
static Octopus instance() {
return Unsafe.getInstance().get();
}
Expand All @@ -31,59 +67,64 @@ static Octopus instance() {
Result<QueryResponse, Error> query(QueryParameter queryParameter);

/**
* <h1>Call</h1>
* <p>
* Stores an object on a key with new revision in the database
* and returns the stored version, including the new revision
* and ID.
* Publishes an object to the given key.
*
* <h2>Expired</h2>
* If an entry is expired. For example a permission, set the expired_at field
* if it's not set and the entry will be flagged as expired
* <p><b>Behavior</b></p>
* <ul>
* <li>Listeners are matched by their {@code keyPattern} (see {@link EventHandler}).</li>
* <li>Wildcard patterns are supported:
* {@code *} matches exactly one token; {@code &gt;} matches zero or more tokens until the end.</li>
* </ul>
*
* <h2>Deletion</h2>
* If an entry should be deleted, just set the deleted_at field and it will be
* flagged as deleted
* <p><b>Errors</b></p>
* <p>
* Implementations may signal failures via an {@code OctopusError} (or another mechanism used by this API).
* </p>
*
* @param obj Object that should be saved inside the database
* @return returns the created {@link studio.o7.octopus.sdk.v1.Entry}
* @param obj the affected object to publish
* @return the stored {@link Entry} on success, otherwise an {@link Error}
*/
Result<Entry, Error> call(studio.o7.octopus.sdk.v1.Object obj);

/**
* <h1>Call</h1>
* Publishes an object to the given key.
*
* <p>
* Stores an object on a key with new revision in the database
* and just forgets it. All listeners will be called
* as usual without blocking this method.
* This operation is fire-and-forget: listeners are triggered asynchronously and this method
* does not block until they complete.
* </p>
*
* <h2>Expired</h2>
* If an entry is expired. For example a permission, set the expired_at field
* if it's not set and the entry will be flagged as expired
* <p><b>Expired entries</b></p>
* <p>
* If an entry should expire (for example, a permission), set its {@code expired_at} field.
* If it is not set, the entry will be flagged as expired.
* </p>
*
* <h2>Deletion</h2>
* If an entry should be deleted, just set the deleted_at field and it will be
* flagged as deleted
* <p><b>Deletion</b></p>
* <p>
* To delete an entry, set its {@code deleted_at} field. The entry will then be flagged as deleted.
* </p>
*
* @param obj Object that should be saved inside the database
* @param obj object that should be saved inside the database
*/
void write(studio.o7.octopus.sdk.v1.Object obj);

/**
* <p>
* A registration of a handler will subscribe to its given key pattern
* and receive all updates on the given key pattern. The handlers `onCall`
* method will be invoked on the incoming {@link studio.o7.octopus.sdk.v1.EventCall}
* </p>
* Registers an {@link EventHandler} (listener) for a key pattern.
*
* <p><b>Pattern rules</b></p>
* <ul>
* <li>Tokens are dot-separated.</li>
* <li>{@code *} matches exactly one token.</li>
* <li>{@code &gt;} matches zero or more tokens until the end of the key.</li>
* </ul>
*
* <p>
* When subscribing, be reminded that the key pattern really matches the requested
* EventCalls, using symbols such as `*` and `<` will subscribe on multiple keys
* There's no safeguard to prevent subscribing to the same topic. So please make
* shure you're not handling a topic twice!
* Example: {@code foo.*.bar} matches {@code foo.x.bar}.<br>
* Example: {@code foo.&gt;} matches {@code foo}, {@code foo.bar}, and {@code foo.bar.baz}.
* </p>
*
* @param eventHandler Handler that will be invoked on matching incoming event
* @param eventHandler the handler to register
*/
void registerHandler(EventHandler eventHandler);

Expand Down