razshare / sveltekit-sse

Server Sent Events with SvelteKit
https://www.npmjs.com/package/sveltekit-sse
MIT License
307 stars 9 forks source link

Readable subscribe does not catch all messages #7

Closed emircanerkul closed 1 year ago

emircanerkul commented 1 year ago
image image

The server sends the data in the correct order, but listeners could not catch time to time.

...
connection.select(EVENT_ENTITY_OUT_OF_SIGHT).subscribe((s)=> {
    console.log(EVENT_ENTITY_OUT_OF_SIGHT ,s);
...
connection.select(EVENT_ENTITY_UPDATE).subscribe((s)=> {
    console.log(EVENT_ENTITY_UPDATE ,s);
...
emircanerkul commented 1 year ago

@tncrazvan I see why this happen. There is a cache per event subscriber. Each time if the data same, the subscriber can not catch it.

Observed th problem via emit(EVENT_ENTITY_OUT_OF_SIGHT, JSON.stringify({...entity, date:Date.now}));

razshare commented 1 year ago

@tncrazvan I see why this happen. There is a cache per event subscriber. Each time if the data same, the subscriber can not catch it.

Observed th problem via emit(EVENT_ENTITY_OUT_OF_SIGHT, JSON.stringify({...entity, date:Date.now}));

Yes, svelte stores will check for safe_not_equal before emitting data.

https://github.com/sveltejs/svelte/blob/d06cfe37239ca64b1a9f9178cfbb8eeaf12f7ffb/packages/svelte/src/runtime/store/index.js#L45-L61

The background event will still send data over the wire.

emircanerkul commented 1 year ago

So, @tncrazvan how can I catch all of those changes? Is there any easy way to override (duplicate) the Svelte runtime store and change in your extension?

Duplicating is easy but also need to change your code (/sveltekit-sse/dist/source.js) too, is there any other easy way?

razshare commented 1 year ago

Version 0.3.0 is out. I've been working all day on this, let me know if this fixes your problem (it should and more).

I've added a new method source::select::transform to the api.

Once you select your event you can now call transform on it and convert it to whatever object you want in real time.

Each transform receives a ReadableStream<string> as a parameter

const connection = source('/events')
const data = connection.select('my-event').transform((stream)=>{
   // your code here...
})

Whatever your callback returns is what you'll get in your const data.

In your case you wanted your store to not filter duplicate messages.

To do that you need to create a custom svelte store.

Note\ If you don't know how to create a custom store I suggest you read this. It's nothing fancy, but you need to understand the svelte store contract.

That being said you can find a full working example in the main README.md file.

I'll also leave here this permalink in case you wanna check the commit.

https://github.com/tncrazvan/sveltekit-sse/blob/52c69ce30dd61892d9d928474b3010af6699d07c/src/components/content.svelte#L4-L36

Result:

Peek 2023-08-20 21-58

emircanerkul commented 1 year ago

@tncrazvan thank you a lot. Your new version worked great. Maybe the possibility of setting the default transformer would be good but it just some spice.

connection.select(EVENT_CURRENT_ENTITY_UPDATE).transform(transformer).subscribe