Closed kmruiz closed 6 years ago
DynamoDBTextStateActor
must extend io.vlingo.actors.Actor
in order to operate asynchronously. Instances must be created via World#actorFor()
or Stage#actorFor()
. Send messages via type-safe interface methods.StateTypeStateStoreMap
method stateTypeToStoreName()
prior to using any given StateStore
. The StateStore
implementation uses StateTypeStateStoreMap
method storeNameFrom()
to get the table/collection/bucket name given a state.dataType
parameter. See source code.State
and the Dispatchable
state. I thought that's why you would use a BatchWriteItemRequest
.write()
the State must be dispatched.Hi Vaughn!
Actually DynamoDB dependencies are all of them but the SDK are for testing purpouses only :D :
Surprisingly is quite fast to download everything.
I have several questions about how to implement the Dispatchable state persistence:
And I have some 'convention' questions :D.
Thanks for your help!
I would say that, by now, I could considered it usable:
Is there anything left to ensure that is working?
@kmruiz I missed a few of your questions:
What should I do if TypeVersion is different? Is there any way to call a migration on the state?
Currently there is no specific migration tools and the differences are left to the application developer to work out the mappings. There will likely be additional tooling provided to help with this, but most of the heavy lifting will still rest on the developer's shoulders.
Needs the persistence actor to implement DispatcherControl?
Yes. The implementation must remove/delete the Dispatchable
from storage when it receives confirmDispatched()
and also arrange for all unconfirmed to be re-dispatched when dispatchUnconfirmed()
is received.
InMemory...
implementations as somehow missing persistence features. You should think of InMemory...
implementations as complete and the persistence of putting to a Map
conceptually the same as disk persistence, including like JDBC and DynamoDB. In other words, think of InMemory...
as the same as disk persistence.Dispatchables should be sent in order of arrival or order of persistence?
I think it depends on the projection implementation, and thus you should offer the parameterized option to operate either sync or async. Still, the Dispatcher
and Projection
should not count on total ordering and/or exactly-once delivery because there could be redelivery caused by slow/failed confirmation, for example. So every kind of sensitive projection should be an idempotent receiver.
Hi! Sorry for the late answer!
I think there are three things left for considering this PR done (correct me if I'm wrong):
Yes, I agree, but just a few clarifications seem appropriate.
The idea of the BinaryStateStore
is that you write and read byte[]
. So you could serialize JSON to bytes, but it would be more like storing a Protobuf serialization. If you mean to use JSON as bytes just for testing, that's fine of course. Did I understand you correctly?
I have already changed NullState
to parameterized NullState<T>
and provided states:
public static NullState<byte[]> Binary = new NullState<>(EmptyBytesData);
public static NullState<String> Text = new NullState<>(EmptyTextData);
I also added a method to the ReadResultInterest
:
void readResultedIn(final Result result, final Exception cause, final String id, final State<T> state);
And also to WriteResultInterest
:
void writeResultedIn(final Result result, final Exception cause, final String id, final State<T> state);
So now you can write code such as:
} catch (Exception e) {
interest.writeResultedIn(Result.Error, e, state.id, state);
}
And like this:
if (storeName == null) {
final String message = "No store mapping for " + type.getName();
interest.readResultedIn(Result.NoTypeStore, new IllegalStateException(message), id, NullState.Binary);
}
Makes sense?
Makes totally sense, actually was the exact part that I was missing for Read/WriteResultInterest. About using Protobuf for the BinaryStore, I think it's a good idea, I can implement it :D.
Thanks for your help!
Excellent, thanks! Also you had some comments about adapting/migrating from one data version to the next. I have some experience with that, and also some ideas. Still, I would like to know what your ideas are, so please share what you have in mind.
Hi!
I've been looking at the documentation of Protocol Buffers:
https://developers.google.com/protocol-buffers/docs/javatutorial
And seems that you need to generate code to make it work and it highly depends on the class that you want to persist. It will generate a class, builders and some serialization code.
I was thinking maybe it's a better idea to use something like MessagePack:
https://msgpack.org/index.html
It's tiny and easy to parse. What do you think?
This is the only thing left to merge this PR.
And about migrations, it's a big topic :D and it doesn't affect only DynamoDB but all persistences, maybe we can create an issue and discuss it there. What do you think?
All good, thanks!
Regarding binary store testing, you don't need Protobuf or MessagePack. I thought you were in need of using a reliable binary serialization tool for a project using vlingo-symbio. For testing it's much easier.
You can just convert a String
to byte[]
as is done here. After you write and then read, you can assert the binary read state against the write state.
When you are ready for merge please comment and I can then merge your work.
When the build is confirmed to be green, it's ready to be merged :D.
Seems that the InMemoryPersistence test somehow had a timeout. I'm going to push an empty commit to run the build again.
@kmruiz You can navigate here and restart the build.
Good to know! I didn't see the option :D! Now everything is green!
@kmruiz Are you ready for a merge or would you prefer doing more work on the binary store before the merge?
@VaughnVernon IMHO it can be merged, I would like to refactor the implementation of record adapters, to reuse more code, but it's a safe refactor that can be done later.
WIP -> Solves issue #1
This is a basic implementation of a DynamoDB state store using the asynchronous DynamoDB client.
Notes
vlingo_${FULL_QUALIFIED_CLASS_NAME_WITH_UNDERSCORES_INSTEAD_OF_DOTS}
. There is an example on the test class.State<Object>
. Java generics are not covariant, so I can not use State.NullState as valid implementation ofState<String>
. I used null at this point, but it should be solved somehow.Current State
Please, give some feedback if you find any issues on the current implementation.