thenativeweb / cqrs-sample Goto Github PK
View Code? Open in Web Editor NEWCQRS, EventSourcing, (DDDD) Sample in node.js
CQRS, EventSourcing, (DDDD) Sample in node.js
I really think CQRS is an interesting way of implementing distributed systems.
However, I have been looking at the sample app for several hours now and the longer I look into it, the more questions it raises.
The documentation link refers to http://adrai.github.io/cqrs/pages/eventdenormalizer.html. But that ain't documentation. The usage samples are ok but what does every single module do? What's it's purpose? What's missing?
I started by shutting down the domain server. Messages where still accepted but surely not handled. The user gets no indication of this whatsoever. Is that considered acceptable or just left out? When left out, what would be needed to add it? What's the added value of the Redis PubSub server?
What if there is more than 1 aggregate? Would every browser (socket) get every message for every aggregate even when not interested or not even authorized? How to deal with that? What about the traffic load?
I am sure these cqrs modules would get used way more if the documentation was improved. I don't feel like inventing the wheel myself but I am also not able to make an estimation as to what it would take to use these modules. And that's a shame, especially because this package looks to be the most thought through one, of the ones available.
Hi Adrai, Thank you for sharing this amazing work.
Please, could I have your opinion (the best way) on how I can integrate GraphQL (Apollo) into this sample ?
Sample is up and running, see form at http://localhost:3000 but can't add any item - field goes empty and nothing else happens. Redis is empty
I had setup my repository for context implementation according to my previous #16
Steps that i followed to implement context:
1 : Used configuration like,
context: 'context.name', aggregate: 'aggregate.name'
in
domain.defineCommand ({ , domain.defineEvent({ , eventDenormalizer.defineEvent({
2 : structured directory for context manufacturing and aggregate item
3 : added context.js
according to manufacturing context
4 : added context: { name: 'mycontext' }
in command
On testing i found readmodel was not generating
On Further debugging i found some mismatch here
query.name = query.name || '';
query.version = query.version || 0;
query.aggregate = query.aggregate || null;
query.context = query.context || null;
var found = _.filter(this.viewBuilders, function (vB) {
return vB.name === query.name &&
(vB.version === query.version || vB.version === -1) &&
(vB.aggregate === query.aggregate) &&
(vB.context === query.context);
});
Due to context setup : query.aggregate = 'narration' & query.context = 'mycontext'
but
on other side in _.filter(this.viewBuilders
,it contains aggregate= null & context = null
in all objects in array
so
nothing matches and it returns empty array
Event Ordering, Concurrency, and Client Reconnect Sync:
Are you ordering the events as they come into the event store, how are you keeping track of the ordering of events when you have multiple clients working on the same data? ... for example you have two users both changing customer information, the first makes a change, that means the second has stale data, then second one makes a change to customer data, but not the same customer data as the first user -- are you keeping track of the event orders, how are you handling concurrency in this case -- say a third use comes online with the customer screen up after being offline for a while, how do you sync up what's happened since he's been offline?
Aggregate Hydration and Snapshots:
How are you populating your aggregate root from your event source with you have 1 million events or more? I understand you're using snapshots on your MongoDb that stores events -- I don't mean taking backups, I mean instead of hydrating your Aggregate Root from your ES from the bottom up, you hydrate from the top down to a "snapshot" or versioned pointer in MongoDb?
Thanks!
Hi @adrai ,
Thank you for your sample,
I don't know if mongodb has changed it's "connect" function interface, but when I change the type of eventStore from "inMemory" to "mongodb", I get the following error:
.../node_modules/mongodb/lib/mongo_client.js:241
throw new TypeError('connect
only accepts a callback');
I'm using mongodb in local.
I'm really interested in testing setup (with mocha) for a new CQRS project.
Using this kind of approach I don't get where to start...
Do you have suggestions?
Many thanks,
Alberto
In your package file it states you have a requirement for Express >= 2.5.0.
I did a npm install -s and got express 4.8.2.
In this version Configure() signature's absent.
I suppose I'll try to install an older version of Express to fix the issue. Should I install version 2.5.0 or what version do you recommend?
Do you use MongoDb as an Event Store (Db) and a Queue? In this case, between the Write and Read you don't need something like zmq or RabbitMQ for messaging correct? If you do use MongoDb as your Queue, where do you use RabbitMQ if anywhere?
Do you use messages between your Aggreate and your Event Store? If so do you use RabbitMQ for this? Do you use the Pipes and Filters pattern? Zmq? Or just Async callbacks?
Apparently this is deprecated in socket.io.
Can you explain why not use just 'revision' for domain and command structure?
Hi Adrai,
Thanks a lot for this sample app, and the rest of the cqrs-code -- much appreciated.
I was just wondering if there was a testing best practice that you used? The key testing point for me would be how events are applied to the aggregate. However, the way the code is structured, the callback used to change the aggregate only gets exposed/exported as a require('cqrs-domain').defineEvent(options, callback)
, which seemingly makes it hard to get to.
I want to do an async action in the callback of require('cqrs-domain').defineCommand(options, callback)
. (I want to use bcrypt should by async.) How would one go about it?
Eg,
module.exports = require('cqrs-domain').defineCommand({
name: 'verbNoun'
}, (data, aggregate) => {
doSomethingAsync(data.value, result => {
aggregate.apply('nounVerb', result)
})
})
When I change EventStore to MongoDb publishing of events to host stops. All other things work perfectly.
I am changing configuration of Server's Eventstore option to MongoDb. Do I have to do anything else too?
Also tried changing all the inMemory configurations to MongoDb, still events do not publish to Host.
Dear adrai,
I'm looking at your implementation of cqrs (cqrs-domain) and the current sample.
I've done couple of CQRS application in C#. I'm pretty new to Javascript and I'm starting to find my way in.
I have a question regarding your sample. When you look at the item aggregate operation, the apply operation is always called before the check business rules. Once the apply is completed, then you check for the business rules.... doesn't this is implemented in the reverse order? Shouldn't you first check the business rules before applying the changes? You could imagine the case where the information in the event might cause the apply to fail. From my experience in CQRS an Apply should never fail unless system errors.
thanks for the good work.
Alex.
Can you put together a sample of what it would look like an aggregate with more than one entity, something like:
Car (root)
Customer (root)
I am having some trouble setting this up, since Customer events can have an effect over the Car aggregate. Can you point me into the right direction?
:) I was trying to use snapshot functionality.Its not producing snapshots
configuration that is used for snapshot:
snapshotThreshold: 2, (snapshot after every 2 events)
1 : on debugging found error in file defultcommandhandler.js : line 370
MongoError key _general.undefined.56710bcd4507c0550bcc1149 must not contain '.'
2: then on further debugging found error here in file aggregateModel.js : line 62
this.get('_revisions')[streamInfo.context + '.' + streamInfo.aggregate + '.' + streamInfo.aggregateId] = rev;
Mongo stores key and values and keys should not contain '.' dott
am i missing some thing in configuration . . ?
Define the event structure in denormalizer.defineEvent
need more understanding on below lines
// optional, only makes sense if contexts are defined in the 'domainPath' structure
context: 'context.name',
// optional, only makes sense if aggregates with names are defined in the 'domainPath' structure
aggregate: 'aggregate.name',
Is this configuration about LOGICAL directory structure ?
EXAMPLE :This is what i am trying to say
cqrs-example
domain
lib
sales (does this stand for CONTEXT .. ?)
salesinvocie(does this stand for AGGREGATES .. ?)
createsalesinvoice.js
deletesalesinvoice.js
salesorder
createsalesorder.js
deletesalesorder.js
salesreceipt
createsalesreceipt.js
deletesalesreceipt.js
purchase(does this stand for CONTEXT)
purchaseorder(does this stand for AGGREGATES)
createpurchaseorder.js
deletepurchaseorder.js
purchasereqisition
createpurchasereqisition.js
deletepurchasereqisition.js
Hello, this is a great example of how to use CQRS and Event Sourcing. I was wondering if i use different domains, a single host (the web application) can i achieve a Microservices Architecture? The documentation is good, but i feel it has more power and i want to use them into a Microservice Architecture. Can you give some advice?
I need more formal example for saga. :)
itemCreated.js saga is not responding
doubt's
1 : i am using onEvent in init function
is there any thing missing :>)
Need Assistance in upgrading cqrs_sample
link to crqs-sample upgrade that i tried
Change List :
1 : updated cqrs-domain , cqrs-eventdenormalizer , viewmodel to latest
2 : corresponding to above 3 core modules i also updated configuration code in server.js
by referencing to nice documentation in each modules.
General doubt
1 : Was It the right way to upgrade your repository( means upgrading module and configuration code in server.js )
2 : Is it ok to use these modules in production . . or there are major updates yet to come .
Code doubt
1 : In domain/server.js file
code snippet from node-cqrs-domain documentation
`domain.onEvent(function (evt, callback) {
msgbus.emit('event', evt, function ack () {
callback();
});
});`
In msgbus.js there is not emit function ..?
2 : In host/server.js file
code snippet from node-cqrs-eventdenormalizer documentation
`eventDenormalizer.onEvent(function (evt, callback) {
msgbus.emit('event', evt, function ack () {
callback();
});
});`
In msgbus.js there is not emit function ..?
Hi @adrai ,
I want to ask what resources (books, blogs, articles, videos...) do you recommend if I want to design a complex architecture based on your modules. (For example how to create bounded context, relationship between them, ...)
I read the documentation of your modules and have a good understanding of microservices, CQRS, ES, but I still have a lot of questions and I want to get it right.
I will really appreciate you input in this.
Thank you in advance.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.