-
Couldn't load subscription status.
- Fork 54
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton
Working PRs
The New Design
In this new design, we will use:
'dirty'event (added via add dirty rpc function definition for sync data grpc#79)dirtyPayload()method (added via add dirtyPayload() and hide others #114)XXXPayloadDirty()method (removed via add dirtyPayload() and hide others #114)
With the logic:
'dirty'event will be emitted by the deepest puppet by calling thedirtyPayload()method:PuppetServiceClient(PuppetServiceServer(PuppetAbstract))).dirtyPayload()->PuppetAbstract.emit('dirty', payload)- Every Puppet listen to
'dirty'event with itsonDirty()method, and invalid(remove) the cache of the payload with the specificidandtype(registeronDirty()callback to thedirtyevent will be done automatically by thePuppetAbstract) XXXPayloadDirty()should calldirtyPayload()first, then wait the'dirty'event. After receiving the'dirty'event, it can return because the payload should be dirtied by the listener (which should be registered by the Puppet itself)- a timer should be added in case of the
'dirty'event was lost, and throw an Error. (5 seconds in the current code)
- a timer should be added in case of the
New Puppet API: onDirty()
onDirty()will beaddListenerto thedirtyevent by thePuppetAbstract- child puppets need to override it to clean their own payload cache/store (and do not forget to call
super.onDirty()!)
Dirty a Payload Locally (in Puppet Provider)
How to dirty a payload (for puppet provider, locally):
puppet.XXXPayloadDirty(id)future = await new Promise(resolve => puppet.once('dirty', resolve))- check the dirty id/type match before resolve
- add a timer to reject the Promise if timeout
puppet.dirtyPayload('XXX', id)setImmediate(() => puppet.emit('dirty', { type: 'XXX', id }))<- add this task (emit) to the end of event loop queue
puppet.onDirty()
2. clean the cachepuppet.XXXPayloadDirty(id)<- future resolvedawait new Promise(setImmediate)<- wait current event loop task queue to be all executed
call 1, emit 2, listen 3, resolve 4
Dirty a Payload Remotely (with Puppet Service)
- 🖥️ Puppet Service
puppetService.XXXPayloadDirty(id)future = await new Promise(resolve => puppet.once('dirty', resolve))- check the dirty id/type match before resolve
- add a timer to reject the Promise if timeout
puppetService.dirtyPayload('XXX', id)gRPC Service DirtyPayload
- ☁️ Puppet Server
puppetServer.dirtyPayload('XXX', id)puppetServer.emit('dirty', { type: 'XXX', id })puppetServer.onDirty()listener: remove payload cachegRPC Service Event (Stream)
- 🖥️ Puppet Service
puppetClient.emit('dirty', { type: 'XXX', id })puppetClient.onDirty()listener: remove payload cachepuppetClient.XXXPayloadDirty(id)future resolved
Steps Mapping
| Locally | Remote Client | Remote Server |
|---|---|---|
| 1 | 1. i | 2.i |
| 2 | 1. ii | 2.ii |
| 3 | 3. ii | 2.iii |
| 4 | 3. iii | 2.iv |
Related issues
- add dirtyPayload() and hide others #114
- No contactPayloadDirty method in puppet-implementation. puppet-service#43
- add dirty rpc function definition for sync data grpc#79
Breaking Change
This change will not affect the end-users.
However, the puppet provider developer needs to follow this new logic when they are using the new version of Puppet Abstract Class.
The Puppet Service will be affected too, so we recommend paying attention to the Wechaty versions to be matching on both the server and the client.
CC @wechaty/puppet @wechaty/grpc
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request