Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Automatic chunked messaging #524

Open
2 tasks done
martonlederer opened this issue Mar 30, 2023 · 2 comments
Open
2 tasks done

[RFC] Automatic chunked messaging #524

martonlederer opened this issue Mar 30, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@martonlederer
Copy link

martonlederer commented Mar 30, 2023

How do you envision this feature/change to look/work like?

The new system would automatically split the message data into pieces that wouldn't reach the size limitation of the browser messaging API. Each piece would then be sent as an ArrayBuffer to the recipient (ArrayBuffers can only be sent as number[]) where it would be stored till it receives all chunks of the data. After that the recipient would reassemble it using the split data and extra information submitted with the chunk. After the reconstruction of the message, the chunks need to be deleted.

There would be 3 different types of chunks:

Init chunks

The first chunk to send, it tells the recipient to start collecting chunks for this chunkCollectionId.

interface InitChunk {
	// chunk type
	type: "init";
	// the index of the chunk (helps to reconstruct the data in order)
	// for init chunks this should always be 0
	index: number;
	// an unique ID for the chunks for this specific message
	// this helps to handle multiple messages at once and not
	// confuse the chunks with other messages' chunks
	chunkCollectionId: number;
	// the total amount of chunks that the original message
	// was split to
	totalChunks: number;
	// the length of the data split into chunks
	dataLength: number;
	// the data of the chunks (can be converted back to an ArrayBuffer)
	data: number[];
}

Data chunks

Data chunks are the simplest chunks sent right after the init chunk has been sent.

interface DataChunk {
	type: "data";
	index: number;
	chunkCollectionId: number;
	data: number[];
}

End chunks

The last chunk to send, it tells the recipient to end the collection of the chunks for this chunkCollectionId.

interface EndChunk {
	type: "end";
	// this should be totalChunks - 1
	index: number;
	chunkCollectionId: number;
	data: number[];
}

Chunked messaging flow process

Here is an sketch of how this would work between a content-script and a background service worker.
Screenshot 2023-03-30 at PM 9 09 18
Screenshot 2023-03-30 at PM 9 11 00
Screenshot 2023-03-30 at PM 9 11 17
Screenshot 2023-03-30 at PM 9 11 33
Screenshot 2023-03-30 at PM 9 11 45

What is the purpose of this change/feature? Why?

In my testings, the maximum allowed size of messages is 67108862 bytes or ~67 Mbs. This means that if you're trying to send a larger message or bytes of a bigger file, you can't use the browser's messaging API.
The solution to this is chunked messaging, where developers don't need to worry about limits, because if they're handling larger data, the messaging library automatically splits their data into chunks, sends it to the message target and reassembles it on the other side. It would be also nice to allow developers to optionally customize max chunk sizes or otherwise use a fixed limit.

Personally, we deal with large data transmissions in the ArConnect extension, sometimes even gigabytes, so we need a permanent solution to send these datas.

Example implementations

A primitive and basic implementation of this can be found at the ArConnect crypto wallet repo:

Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I checked the current issues for duplicate problems.
@martonlederer martonlederer added the enhancement New feature or request label Mar 30, 2023
@martonlederer
Copy link
Author

I've been thinking a lot about making this feature optional or specific to a type of messaging API. I've found that the best option we have is to implement this for long lived connection ports only.
The main reason for this is that the basic message flow is for smaller messages anyway and ports are for bigger data / longer data transfer time. It is also much easier to implement this with ports and I'm afraid the service worker could shut down after some time if we did this with the normal chrome.runtime.sendMessage flow.

@spookyuser
Copy link

Running into this problem now, another solution might be - although prob a different RFC - but using Transferables with postMessage like over here https://groups.google.com/a/chromium.org/g/chromium-extensions/c/UyNHEHQKlJA/m/it_eC58DAwAJ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants