CQRS Wechaty
An event-driven architecture wrapper for Wechaty that applies the CQS principle by using separate Query and Command messages to retrieve and modify the bot state, respectively.
Image source: Introducing Derivative Event Sourcing
Command Query Responsibility Separation (CQRS)
Command query responsibility separation (CQRS) generalises CQS to message-driven and event-driven architectures: it applies the CQS principle by using separate Query and Command messages to retrieve and modify data, respectively.
Image source: CQRS (command query responsibility segregation)
Motivation
Can we use Wechaty by only sending / receiving the Plain Old JavaScript Object (POJO)?
That's an Event-driven way, which will give us the following benifites:
- Better integration with Domain-driven Design (DDD)
- Decouple the sub-systems with the Wechaty instance completely
- Enable using Wechaty with Microservices
- Make it possible for providing an API endpoint with JSON request/responses
- etc.
So we decided to support the Event-driven Architecture by enabling the Event-driven Programming with Wechaty by publishing the wechaty-cqrs NPM module.
Features
- Convert Wechaty instance to a messaging
bus$
with thefrom()
function. - Well-defined
commands
,queries
,responses
, andevents
payload creators. - A great
execute$()
helper function for sending the events to the bus and get back the response. - Well-defined
events$
for the Wechaty events - Well-defined
sayables
for build all the message contents - Static typing with TypeScript with all events & streams
- Working perfect with the powerful RxJS
Usage
Install
npm install wechaty-cqrs wechaty
Quick start
Here's the CQRS version of the Wechaty ding/dong bot:
import * as CQRS from 'wechaty-cqrs'
import * as WECHATY from 'wechaty'
import { filter, map, mergeMap } from 'rxjs/operators'
const wechaty = WECHATY.WechatyBuilder.build()
await wechaty.init()
const bus$ = CQRS.from(wechaty)
bus$.pipe(
filter(CQRS.isActionOf(CQRS.actions.messageReceivedEvent)),
// MessageReceivedEvent -> Sayable
map(messageId => CQRS.duck.actions.getSayablePayloadQuery(
messageReceivedEvent.meta.puppetId,
messageId,
)),
mergeMap(CQRS.execute$(bus$)(CQRS.duck.actions.getSayablePayloadQueryResponse)),
// Log `sayable` to console
).subscribe(sayable =>
console.info('Sayable:', sayable),
)
bus$.next(CQRS.duck.actions.startCommand(wechaty.puppet.id))
Getting Started
Here's a video introduction for CQRS Wechaty with live demo, presented by Huan:
YouTube: https://youtu.be/kauxyPVa0jo
The getting started ding-dong-bot.ts in the video: https://github.com/wechaty/getting-started/blob/main/examples/cqrs/ding-dong-bot.ts
Diagrams
graph LR
classDef event fill:DarkGoldenRod
classDef command fill:blue
classDef query fill:green
subgraph Command
C(VerbNounCommand):::command
end
subgraph Response
RC(VerbNounCommandResponse)
RQ(GetNounQueryResponse)
end
subgraph Query
Q(GetNounQuery):::query
end
subgraph Event
ER(ReceivedEvent):::event
end
C-->RC
ER-->ER
Q-->RQ
Command
sequenceDiagram
participant Bus
participant Redux
participant Wechaty
Bus->>Redux: ExecuteCommand
Redux->>Wechaty: Call
Wechaty->>Redux: Call Return (void)
Redux->>Bus: ExecuteCommandResponse
Query
sequenceDiagram
participant Bus
participant Redux
participant Wechaty
Bus->>Redux: GetNounQuery
Redux->>Wechaty: Call
Wechaty->>Redux: Call Return (value)
Redux->>Bus: GetNounQueryResponse
Event
sequenceDiagram
participant Bus
participant Redux
participant Wechaty
Wechaty->>Redux: ReceivedEvent
Redux->>Bus: ReceivedEvent
API Reference
Read CQRS Wechaty API Reference at: https://paka.dev/npm/wechaty-cqrs
Blogs
Resources
- Layers in DDD microservices
- Effective Aggregate Design
- Domain-Application-Infrastructure Services pattern
History
main
v0.10 (Mar 17) Beta release
- v0.9 (Mar 17,2022): Refactoring(clean) module exports
- v0.7 (Mar 16, 2022): Refactoring
execute$
withduck.actions
builders. - v0.6 (Mar 13, 2022): Alpha release.
- v0.4 (Mar 13, 2022): CQRS Ding/Dong BOT works as expected.
- v0.2 (Mar 11, 2022): Unit tests all passed, DevOps enabled.
- v0.0.1 (Mar 6, 2022): Init README & Draft design.
Author
Huan LI (李卓桓), Microsoft Regional Director, [email protected]
Copyright & License
- Code & Docs © 2022 Huan (李卓桓) <[email protected]>
- Code released under the Apache-2.0 License
- Docs released under Creative Commons