Agent status should be changed immediately on calling close
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 6.5k
- Forks
- 456
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 5
Description
In the close function of an Agent, we call end on the stream.
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L54
And later on when event listeners for end event are called, it will call _cleanup in which we will change the status of the agent to closed.
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L247
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L250
But in between this time interval, if any operation comes up, it will write to the closed stream and ERR_STREAM_WRITE_AFTER_END will be thrown. I'm able to reproduce this following way:
- Client A creates doc
- Client B subscribes to it and does some operations
- Some time later on, server wants to delete this doc due to some foo reason.
- Server closes all the agents connected to that doc.
- Server creates a new connection to the backend, fetches the same document and in the callback of the fetch, it sends delete operation on it.
What happens next:
- Backend receives delete request and forwards it to all the agents.
- Agent's status hasn't been changed to
closedyet. - Agent tries to write data to stream on which
endhad been called earlier and boom!
Stacktrace:
events.js:167
throw er; // Unhandled 'error' event
^
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at writeAfterEnd (_stream_writable.js:243:12)
at WebSocketJSONStream.Writable.write (_stream_writable.js:291:5)
at Agent.send (/foobar/node_modules/sharedb/lib/agent.js:165:15)
at Agent._sendOp (/foobar/node_modules/sharedb/lib/agent.js:181:8)
at OpStream.<anonymous> (/foobar/node_modules/sharedb/lib/agent.js:103:11)
at OpStream.emit (events.js:182:13)
at OpStream.EventEmitter.emit (domain.js:442:20)
at addChunk (_stream_readable.js:279:12)
at readableAddChunk (_stream_readable.js:264:11)
at OpStream.Readable.push (_stream_readable.js:219:10)
at /foobar/node_modules/sharedb/lib/op-stream.js:38:14
at Backend.trigger (/foobar/node_modules/sharedb/lib/backend.js:190:20)
at Backend._sanitizeOp (/foobar/node_modules/sharedb/lib/backend.js:235:8)
at OpStream.pushOp (/foobar/node_modules/sharedb/lib/op-stream.js:36:18)
at MemoryPubSub.PubSub._emit (/foobar/node_modules/sharedb/lib/pubsub/index.js:94:26)
at /foobar/node_modules/sharedb/lib/pubsub/memory.js:33:16
at process._tickCallback (internal/process/next_tick.js:61:11)
So, I believe status of the agent should be changed in the close function itself.
https://github.com/share/sharedb/blob/68bde0047eccd4709bd41e64f380ea7841f9864f/lib/agent.js#L58
@gkubisa If you believe what I have stated above is correct, I would like to see it merged in https://github.com/teamwork/sharedb
Thanks!
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/agent.js at Agent.close, then compare the status update in _cleanup and the send path shown in the stack trace. Reproduce the close-then-operation sequence described in the issue and verify that an agent cannot write to the stream after close has been called.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 55/100