Skip to content

Instantly share code, notes, and snippets.

@jen20
Created May 19, 2015 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jen20/f061db530ae401765aeb to your computer and use it in GitHub Desktop.
Save jen20/f061db530ae401765aeb to your computer and use it in GitHub Desktop.
A first stab at an EventStoreConnection interface for a new pure Java client
package com.geteventstore.client;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface EventStoreConnection {
CompletableFuture connect();
void close();
CompletableFuture<WriteResult> appendToStream(String streamName, int expectedVersion, EventData[] events);
CompletableFuture<DeleteResult> deleteStream(String streamName, int expectedVersion);
CompletableFuture<StreamEventsSlice> readEventsForward(String streamName, int start, int count, Boolean resolveLinks);
CompletableFuture<StreamEventsSlice> readEventsBackward(String streamName, int start, int count, Boolean resolveLinks);
CompletableFuture<SingleReadResult> readEvent(String streamName, int eventNumber, Boolean resolveLinks);
CompletableFuture<Subscription> subscribeToStreamLive(String streamName,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop);
CompletableFuture<Subscription> subscribeToStreamLive(String streamName,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Executor executor);
CompletableFuture<Subscription> subscribeToAllLive(LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop);
CompletableFuture<Subscription> subscribeToAllLive(LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Executor executor);
CompletableFuture<Subscription> subscribeToStreamFromEventNumber(String stream,
int eventNumber,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Consumer<Subscription> onLiveProcessingStart);
CompletableFuture<Subscription> subscribeToStreamFromEventNumber(String stream,
int eventNumber,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Consumer<Subscription> onLiveProcessingStart,
Executor executor);
CompletableFuture<Subscription> subscribeToAllFromPosition(Position position,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Consumer<Subscription> onLiveProcessingStart);
CompletableFuture<Subscription> subscribeToAllFromPosition(Position position,
LinkAction linkAction,
BiConsumer<Subscription, ResolvedEvent> onEvent,
BiConsumer<Subscription, DropReason> onDrop,
Consumer<Subscription> onLiveProcessingStart,
Executor executor);
}
@jen20
Copy link
Author

jen20 commented May 19, 2015

Still to do: some way of passing user credentials. Some options here that I can think of:

  1. Make the credentials global for the connection (don't like this as it prevents meaningful connection pooling)
  2. Duplicate all the methods with a UserCredentials type as a final parameter
  3. Use an Optional on all the methods

Opinions welcome.

@jen20
Copy link
Author

jen20 commented May 19, 2015

Also still to do, persistent subscriptions, though will likely add them later rather than in a first version of this.

@jen20
Copy link
Author

jen20 commented May 19, 2015

Also if anyone can come up with a better pattern than passing in Executors on a duplicated set of methods that would be nice, especially if there's an option of using a default one still (likely a thread pool).

@michael-schnell
Copy link

I'm currently in the process of creating a common API for different event store implementations. The project is called event-store-commons and it also will provide some implementations itself (InMemory, JPA). It will also provide some kind of "Given/When/Then" style tests (First exmple is here) to evaulate that all event store implementations work the same according to the API.

The project is still work in progress, but your proposal might be a good way to cross-check or align the two approaches.

At the moment I have two interfaces: ReadOnlyEventStore and WritableEventStore. I guess there will be a third one for event stores that have a way to subscribe to them (SubscribableEventStore).

I'll check your proposal and get back soon on that topic.

@michael-schnell
Copy link

Regading the "Executor" and "User Credentials" - How about passing them with "connect" (Also I'd prefer more the method name "open()" (as opposed to "close()").

@jen20
Copy link
Author

jen20 commented May 20, 2015

@michael-schnell I think having a default set of credentials and a default executor passed in on Connect is certainly valid.

However, I think we need to retain the option for e.g. a different thread pool for each subscription, and also user credentials per operation such that meaningful connection pooling is actually possible here.

I'll take a look over your interfaces soon - thanks for replying!

@michael-schnell
Copy link

The interface looks nice and clean.

Could you provide the source for the other objects like "EventData", "*Result", "Subscription", "ResolvedEvent", "SingleReadResult" ... ? This would help to understand the overall approach - For example: Do you pass byte arrays as data or Java objects inside the events? (For example in case of ESJ Java objects are passed and this requires some kind of serialization/deserialization mechanism to be included into the implementation.)

Findings:

  • "EventData[] events" should be an open array " EventData...events"
  • There should also be a collection version: "Collection<EventData> events"
  • Some constants should be added to the interface for the "expectedVersion" stuff (VERSION_ANY = -2 / VERSION_NO_STREAM = -1 / VERSION_EMPTY_STREAM = 0)

Questions:

  • What is "LinkAction"? (I guess in case you pass "resolveLinks" arg, there will be some action executed for every link?)

@jen20
Copy link
Author

jen20 commented May 27, 2015

@michael-schnell yes I'll create a repository for it and put the entire interface in there. Stand by for the repository address. Sorry for the delay, it was a holiday weekend.

To address your specific points:

  • Using varargs for the EventData is probably a good idea
  • A collection version is likely also a good idea
  • Constants are likely a good idea. Unlike the .NET client we're not bound by backwards compatibility constraints, so we don't need to deal with Empty stream which is an artefact of a feature which no longer exists.
  • LinkAction is an enumeration of NoAction and ResolveLinks - if you choose to resolve them then link events will be dereferenced in the server which reduces the number of roundtrips required.

@jen20
Copy link
Author

jen20 commented May 27, 2015

@michael-schnell the repository is here: https://github.com/jen20/EventStore.Java - let's move this discussion to the issues section of that repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment