hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.73k stars 429 forks source link

[Proposal] turbo-stream action 'versioning' #906

Open mbell697 opened 1 year ago

mbell697 commented 1 year ago

I'm using turbo-streams for a project and have noticed that in certain circumstances stream actions can be delivered out of order, an older update arriving after a newer update.

A concrete example would be replying from a rails controller directly with a turbo-stream action, but there also being a background job enqueued during that request that sends turbo-stream actions over actioncable. We've see the update from the background job arrive first with fresher data, only to have the controller turbo stream then arrive later replacing the dom content with stale data.

I think it would be a great feature to be able to provide an ordering key (version) along with the each action and have the update code reject the update if the value currently in the dom is smaller.

For example, if this sequence of actions arrived in the browser in this order:

<turbo-stream action="append" target="item" version="1"></turbo-stream>
<turbo-stream action="replace" target="item" version="3"></turbo-stream>
<turbo-stream action="replace" target="item" version="2"></turbo-stream>

The final action with version 2 would be rejected because 3 is the current version in the dom.

In practical applications, version would often be an updated_at timestamp.

I think this feature could be implemented with a simple stimulus controller for my particular situation, but I suspect it's common enough to belong in turbo-stream.

If interested in this feature - I'm happy to open a PR for it.

phylor commented 2 months ago

@brunoprietog Is there any plan to include versioning in turbo stream actions, to avoid out-of-order updates? In my experience, running stale actions happens more often than one might think. It's especially noticeable when implementing progress updates, as the "finished" message might arrive before the last "loading" message, thus not updating correctly. Having a versioning builtin would be awesome!

dhh commented 1 month ago

I like this idea. Please do explore an implementation.