Skip to content
Permalink
Browse files

readme.md rework

add contributing.md, small fixes in demo apps. Fix spellings.
  • Loading branch information...
egetman committed Oct 14, 2019
1 parent 08af1e7 commit 9a0ab24d25854cfb9abec8feb3d35fc253e81b7b
@@ -0,0 +1,20 @@
# Contributing how-to

Thanks for your interest in contributing!

## How to report a bug?

* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/egetman/jes/issues).

* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/egetman/jes/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.


## How to add a new feature or change an existing one

Before making any significant changes, please [open an issue](https://github.com/egetman/jes/issues). Discussing your proposed changes ahead of time will make the contribution process smooth for everyone.

Once we've discussed your changes and you've got your code ready, make sure that tests are passing and open your pull request. Your PR is most likely to be accepted if it:

* Update the README.md with details of changes to the interface.
* Includes tests for new functionality.
* References the original issue in the description, e.g. "Resolves #100500".
@@ -53,7 +53,7 @@
<dependency>
<groupId>store.jesframework</groupId>
<artifactId>jes-core</artifactId>
<version>0.2.0</version>
<version>1.0.0</version>
</dependency>

<dependency>
@@ -70,6 +70,7 @@
</dependencies>

<build>
<finalName>read-part-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
@@ -7,7 +7,7 @@
</encoder>
</appender>

<logger name="store.jesframework" level="all" additivity="false">
<logger name="store.jesframework" level="debug" additivity="false">
<appender-ref ref="stdout"/>
</logger>

@@ -43,14 +43,15 @@
<dependency>
<groupId>store.jesframework</groupId>
<artifactId>jes-core</artifactId>
<version>0.2.0</version>
<version>1.0.0</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -59,6 +60,7 @@
</dependencies>

<build>
<finalName>write-part-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
@@ -57,8 +57,8 @@ public AggregateStore aggregateStore(JEventStore eventStore) {
return new AggregateStore(eventStore);
}

// U can use any aliases for events. So u don't need to hardcode serialized class name of event.
// Every client can create it's own model to deserialize events from event store just using aliasing.
// You can use any aliases for events. So u don't need to hardcode serialized class name of the event.
// Every client can create its model to deserialize events from event store just using aliasing.
@Bean
public SerializationOption[] serializationOptions() {
final TypeRegistry registry = new TypeRegistry();
@@ -5,10 +5,9 @@

import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import store.jesframework.AggregateStore;
import store.jesframework.JEventStore;
import store.jesframework.bus.CommandBus;
import store.jesframework.lock.Lock;
import store.jesframework.offset.Offset;
@@ -18,17 +17,17 @@
import store.jesframework.writemodel.domain.Item;
import store.jesframework.writemodel.event.OrderPlaced;

@Component
@Service
public class OrderSaga extends Saga {

private final CommandBus bus;
private final AggregateStore aggregateStore;

public OrderSaga(@Nonnull JEventStore store, @Nonnull Offset offset, @Nonnull Lock lock, @Nonnull CommandBus bus,
@Nonnull AggregateStore aggregateStore) {
super(store, offset, lock);
public OrderSaga(@Nonnull AggregateStore aggregateStore, @Nonnull Offset offset, @Nonnull Lock lock,
@Nonnull CommandBus bus) {
super(aggregateStore, offset, lock);
this.bus = Objects.requireNonNull(bus, "CommandBus must not be null");
this.aggregateStore = Objects.requireNonNull(aggregateStore, "AggregateStore must not be null");
this.aggregateStore = aggregateStore;
}

@ReactsOn
@@ -7,7 +7,7 @@
</encoder>
</appender>

<logger name="store.jesframework" level="all" additivity="false">
<logger name="store.jesframework" level="debug" additivity="false">
<appender-ref ref="stdout"/>
</logger>

@@ -6,7 +6,7 @@

<groupId>store.jesframework</groupId>
<artifactId>jes-core</artifactId>
<version>0.2.0</version>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>Jes</name>
136 readme.md
@@ -1,5 +1,5 @@
[![actions status](https://github.com/egetman/jes/workflows/Jes%20build/badge.svg)](https://github.com/egetman/jes/actions)
![version](https://img.shields.io/badge/version-0.2.0-green.svg)
![version](https://img.shields.io/badge/version-1.0.0-green.svg)
![code coverage](https://codecov.io/gh/egetman/jes/branch/master/graph/badge.svg)
![apache license](https://img.shields.io/hexpm/l/plug.svg)
[![maven central](https://img.shields.io/maven-central/v/store.jesframework/jes-core.svg?label=maven%20central)](https://search.maven.org/search?q=g:%22store.jesframework%22%20AND%20a:%22jes-core%22)
@@ -86,133 +86,11 @@ core | |
flow | |
&#xfeff;| optimistic locking | perfect for user-related communication

## Components overview
You can find components overview on the related [wiki page](https://github.com/egetman/jes/wiki/Components-overview).

## Jes basics
Central library element is `JEventStore`. It provides basic functionality for managing events in your system:
## Example configuration
You can find spring-related example configuration on the [wiki page](https://github.com/egetman/jes/wiki/Example-of-Spring-Boot-Config).

```java
public class JEventStore {
public JEventStore(@Nonnull StoreProvider provider) {
...
}
public Stream<Event> readFrom(long offset) {...}
public Collection<Event> readBy(@Nonnull UUID uuid) {...}
// etc...
}
```
`StoreProvider` is an actual component that incapsulates all interaction with concrete store.
Currently `StoreProvider` can be built on top of the database.
There are 2 implementations of `StoreProvider` to use: `JdbcStoreProvider` & `JpaStoreProvider`:

```java
public class JdbcStoreProvider<T>... {
public JdbcStoreProvider(@Nonnull DataSource dataSource, @Nonnull Class<T> serializationType,
@Nonnull SerializationOption... options) {
}
public class JpaStoreProvider<T>... {
public JpaStoreProvider(@Nonnull EntityManagerFactory entityManagerFactory, @Nonnull Class<T> serializationType,
@Nonnull SerializationOption... options) {
}
```
`serializationType` can be `String.class` or `byte[].class`, which will create json / binary serializers implemented
on top of Jackson / Kryo respectively.
To work with `Aggregates` you can use `AggregateStore`:
```java
public class AggregateStore {
public AggregateStore(@Nonnull JEventStore eventStore) {...}
public AggregateStore(@Nonnull JEventStore eventStore, @Nonnull SnapshotProvider snapshotProvider) {...}
public <T extends Aggregate> T readBy(@Nonnull UUID uuid, @Nonnull Class<T> type) {...}
// etc...
}
```
If `SnapshotProvider` specified, aggregate fetching is snapshotted.
`SnapshotProvider` can be any of `NoopSnapshotProvider`, `InMemorySnapshotProvider`, `JdbcSnapshotProvider`,
`RedisSnapshotProvider`.
There is also basic support for projectors via:
```java
public abstract class Projector extends Reactor {
public Projector(@Nonnull JEventStore store, @Nonnull Offset offset, @Nonnull Lock lock) {...}
}
```
To make it work - extend it and mark the needed methods with `@ReactsOn` annotation:
```java
@ReactsOn
private void handle(@Nonnull SmthHappend event) {
...
}
```
## Usage
If you are familiar with `Spring`, the typical configuration of `Jes` may look like:
```java
@Configuration
@EnableAutoConfiguration
public class JesConfig {
@Bean
public StoreProvider jdbcStoreProvider(DataSource dataSource) {
return new JdbcStoreProvider<>(dataSource, String.class);
}
@Bean
public JEventStore eventStore(StoreProvider storeProvider) {
return new JEventStore(storeProvider);
}
@Bean
public SnapshotProvider snapshotProvider() {
return new InMemorySnapshotProvider();
}
@Bean
public AggregateStore aggregateStore(JEventStore eventStore, SnapshotProvider snapshotProvider) {
return new AggregateStore(eventStore, snapshotProvider);
}
@Bean
public Offset offset() {
// you can use RedisOffset if you use Redis
return new InMemoryOffset();
}
@Bean
public Lock lock() {
// you can use RedisReentrantLock if you use Redis
return new InMemoryReentrantLock();
}
@Bean
public Projector userProjector(JEventStore eventStore, Offset offset, Lock lock) {
return new UserProjector(eventStore, offset, lock);
}
}
```
## Todo:
- version caching? to avoid every-write check
- snapshots invalidation: describe or reimplement
- store structure validation on start
- ~~event idempotency on read (clustered environment)~~ done by locking for projectors
- string (xml) serializer (xstream?): use SerializationOption to specify type?
- upcasting
- lazy transformation
- ~~verify serialization/deserialization of abstract classes/interface references~~
- ~~don't fail on unknown events~~ done via common event type for unregistered events
- make reactors pull-mechanism customisable (for db CDC?)
- ~~add demo app~~
- ~~add InMemoryStoreProvider (H2 or just collections?) for testing && H2 support~~
###### PRs are welcome
## Contributing
Please refer to the [contributing guide](contributing.md).

0 comments on commit 9a0ab24

Please sign in to comment.
You can’t perform that action at this time.