1
1
# Akka Persistence Plugin for MongoDB
2
2
[ ![ CircleCI] ( https://circleci.com/gh/null-vector/akka-reactivemongo-plugin.svg?style=svg )] ( https://circleci.com/gh/null-vector/akka-reactivemongo-plugin )
3
3
[ ![ codecov] ( https://codecov.io/gh/null-vector/akka-reactivemongo-plugin/branch/master/graph/badge.svg )] ( https://codecov.io/gh/null-vector/akka-reactivemongo-plugin )
4
+ [ ![ Download] ( https://api.bintray.com/packages/null-vector/releases/akka-reactivemongo-plugin/images/download.svg ) ] ( https://bintray.com/null-vector/releases/akka-reactivemongo-plugin/_latestVersion )
4
5
5
6
This implementation use the [ reactivemongo drive] ( http://reactivemongo.org/ ) .
6
7
7
8
## Installation
8
- This plugin support scala ` 2.12 ` and ` 2. 13` , akka ` 2.6.1 ` and reactivemongo ` 0.18.x ` and ` 0.20.x ` .
9
+ This plugin support scala ` 2.13 ` , akka ` 2.6.10 ` and reactivemongo ` 1.0.0 ` .
9
10
10
11
Add in your ` build.sbt ` the following lines:
11
12
``` scala
12
13
resolvers += Resolver .bintrayRepo(" null-vector" , " releases" )
13
14
```
14
- For reactivemongo ` 0.18.x ` use:
15
-
16
- [ ![ Download] ( https://api.bintray.com/packages/null-vector/releases/akka-reactivemongo-plugin/images/download.svg?version=1.2.11 ) ] ( https://bintray.com/null-vector/releases/akka-reactivemongo-plugin/1.2.11/link )
17
-
18
15
``` scala
19
- libraryDependencies += " null-vector" %% " akka-reactivemongo-plugin" % " 1.2.x"
20
- ```
21
- For reactivemongo ` 0.20.x ` use:
22
-
23
- [ ![ Download] ( https://api.bintray.com/packages/null-vector/releases/akka-reactivemongo-plugin/images/download.svg ) ] ( https://bintray.com/null-vector/releases/akka-reactivemongo-plugin/_latestVersion )
24
-
25
- ``` scala
26
- libraryDependencies += " null-vector" %% " akka-reactivemongo-plugin" % " 1.3.x"
16
+ libraryDependencies += " null-vector" %% " akka-reactivemongo-plugin" % " 1.4.0"
27
17
```
28
18
29
19
## Configuration
@@ -39,44 +29,15 @@ akka-persistence-reactivemongo {
39
29
See [ Connect to a database] ( http://reactivemongo.org/releases/0.1x/documentation/tutorial/connect-database.html ) for more information.
40
30
41
31
## Events Adapters
42
- Before save any event for you ` PersistentActor ` it is needed to add the corresponding ` EventAdapter ` .
43
-
44
- Events adapters must extends from ` org.nullvector.EventAdapter[E] ` , for example:
45
-
46
- ``` scala
47
- class UserAddedEventAdapter extends EventAdapter [UserAdded ] {
48
-
49
- private implicit val userAddedMapping : BSONDocumentHandler [UserAdded ] = Macros .handler[UserAdded ]
50
-
51
- override val manifest : String = " UserAdded"
52
-
53
- override def payloadToBson (payload : UserAdded ): BSONDocument = BSON .writeDocument(payload).get
54
-
55
- override def bsonToPayload (doc : BSONDocument ): UserAdded = BSON .readDocument(doc).get
56
-
57
- }
58
- ```
59
- And then you have to register the new Adapter:
60
- ``` scala
61
- val serializer = ReactiveMongoEventSerializer (system)
62
-
63
- serializer.addEventAdapter(new UserAddedEventAdapter )
64
- ```
65
- A more simple way to create an event adapter by hand is using ` EventAdapterMapping ` :
66
- ``` scala
67
- implicit val mapping : BSONDocumentMapping [SolarPlanet ] = EventAdapterFactory .mappingOf[SolarPlanet ]
68
- val eventAdapter = new EventAdapterMapping [SolarPlanet ](manifest = " planet" )
69
- ```
70
- ## EventAdapter Factory
71
- To avoid writing boilerplate code creating Event Adapters, we can use the ` EventAdapterFactory ` :
32
+ Before save any event from your persistent actor it is needed to register the corresponding ` EventAdapter ` .
72
33
``` scala
73
34
case class ProductId (id : String ) extends AnyVal
74
35
case class InvoiceItem (productId : ProductId , price : BigDecimal , tax : BigDecimal )
75
36
case class InvoiceItemAdded (invoiceItem : InvoiceItem )
76
37
77
38
val eventAdapter = EventAdapterFactory .adapt[InviceItemAdded ](withManifest = " InvoceItemAdded" )
78
39
79
- ReactiveMongoEventSerializer (ActorSystem () ).addEventAdapter(eventAdapter)
40
+ ReactiveMongoEventSerializer (actorSystem ).addEventAdapter(eventAdapter)
80
41
```
81
42
It is also possible to override mappings or add unsupported mappings. All added mappings must extends from ` BSONReader[_] ` or ` BSONWriter[_] ` or both.
82
43
``` scala
@@ -101,16 +62,27 @@ case class InvoiceLineAdded(line: InvoiceLine)
101
62
implicit val conf = MacroConfiguration (discriminator = " _type" , typeNaming = TypeNaming .SimpleName )
102
63
val eventAdapter = EventAdapterFactory .adapt[InvoceLineAdded ](withManifest = " InvoiceLineAdded" )
103
64
```
65
+ Behind the scene ` EventAdapterFactory ` use the ReactiveMongo Macros, so you can configure the BSON mappings:
66
+ ``` scala
67
+ implicit val conf : Aux [MacroOptions ] = MacroConfiguration (discriminator = " _type" , typeNaming = TypeNaming .SimpleName )
68
+ ```
69
+ ### Custom mappings
70
+ You can create mappings by hand:
71
+ ``` scala
72
+ implicit val a : BSONDocumentMapping [SolarPlanet ] = EventAdapterFactory .mappingOf[SolarPlanet ]
73
+ val eventAdapter = new EventAdapterMapping [SolarPlanet ](" planet" )
74
+
75
+ serializer.addEventAdapter(eventAdapter)
76
+ ```
104
77
105
78
## Persistence Id
106
- By default the persistence id has the following form: ` <Aggregate>-<Id> ` , and the aggregate will be the name of the journal collection.
79
+ By default, the persistence id has the following form: ` <Aggregate>-<Id> ` , and the aggregate will be the name of the MongoDB collection.
107
80
108
- You can change the persistence id format by adding your own collection extractor name, implementing the trait ` org.nullvector.CollectionNameMapping ` ,
109
- and registering in the configuration:
81
+ You can change the persistence id separator character:
110
82
```
111
83
akka-persistence-reactivemongo {
112
84
mongo-uri = "mongodb://localhost/test?rm.failover=900ms:21x1.30"
113
- collection-name-mapping = "org.nullvector.DefaultCollectionNameMapping"
85
+ persistence-id-separator = |
114
86
}
115
87
```
116
88
@@ -119,17 +91,16 @@ akka-persistence-reactivemongo {
119
91
Here are some examples of how to use persistence query:
120
92
``` scala
121
93
val readJournal = ReactiveMongoJournalProvider (system).scaladslReadJournal
122
-
123
94
val tagsSource : Source [EventEnvelope , NotUsed ] = readJournal.currentEventsByTag(" some_tag" , NoOffset )
124
95
125
96
tagsSource.runWith(Sink .foreach{ envelope => envelope.event match {
126
97
case UserAdded (name, age) => // Do Something
127
98
}})
128
99
```
129
100
130
- Sometime is necesary to create an Offset:
101
+ Sometime is necessary to create an Offset:
131
102
``` scala
132
- val offset = ObjectIdOffset (DateTime .now())
103
+ val offset = ObjectIdOffset .fromDateTime (DateTime .now()) // A Joda DateTime
133
104
```
134
105
For streams that never complete like ` #persistenceIds ` , ` #eventsByTag ` , etc. it is possible to configure the interval that pulls from the journal:
135
106
```
@@ -147,3 +118,11 @@ If you want different refresh intervals from different query, you can add a `Ref
147
118
.addAttributes(RefreshInterval (700 .millis))
148
119
.runWith(Sink .foreach(println))
149
120
```
121
+
122
+ # Test Driven Development
123
+ Here is a great feature for TDD lovers: it is possible to configure the plugin to persist in memory and reduce the test latency more than half.
124
+ ```
125
+ akka-persistence-reactivemongo {
126
+ persist-in-memory = true
127
+ }
128
+ ```
0 commit comments