foobar
foobar4mo ago

Share a data between multiple instances Deno Deploy

Hi, I want to share data between multiple instance. My first instance create a key. Others new instances have to get the original key from first instance. I use BroadcastChannel to do it. But it relies on the strong assumption that the first instance can't dissapear ? Is it true ? Or do you have a more elegant way to do it (kv ?) ?
/**
* Channel for broadcasting key
*/
const channel = new BroadcastChannel("KEY");

let firstInstance = true;
// all reload generate a new key
let key = generateKey()

channel.onmessage = async (event: MessageEvent<Message>) => {
const message = event.data;
if (message.nature === "newinstance" && firstInstance) {
// only first instance send key
// QUESTION : can first instance disappear
channel.postMessage({ nature: "key", data: key });
}
if (message.nature === "key" && firstInstance) {
// only last instance change
key = message.data;
// it is a new instance
firstInstance = false;
}
};

/**
* All instance post the message
* if 1 instance => no post
* if 2nd instance => only 1st instance receive message => send key
* if 3rd instance => only 1st instance send message because 2nd instance has firstInstance = false
*/
channel.postMessage({ nature: "newinstance" });
/**
* Channel for broadcasting key
*/
const channel = new BroadcastChannel("KEY");

let firstInstance = true;
// all reload generate a new key
let key = generateKey()

channel.onmessage = async (event: MessageEvent<Message>) => {
const message = event.data;
if (message.nature === "newinstance" && firstInstance) {
// only first instance send key
// QUESTION : can first instance disappear
channel.postMessage({ nature: "key", data: key });
}
if (message.nature === "key" && firstInstance) {
// only last instance change
key = message.data;
// it is a new instance
firstInstance = false;
}
};

/**
* All instance post the message
* if 1 instance => no post
* if 2nd instance => only 1st instance receive message => send key
* if 3rd instance => only 1st instance send message because 2nd instance has firstInstance = false
*/
channel.postMessage({ nature: "newinstance" });
6 Replies
Deno AI Helper
Deno AI Helper4mo ago
I wasn't able to find the answer to your question in the official Deno documentation. However, based on the code snippet you've provided, I can offer some general advice, but please note that this advice is not based on the Deno documentation, and you should double check the accuracy of the advice given. In your code, you are using BroadcastChannel to communicate between instances. It's important to note that BroadcastChannel is designed for communication between browsing contexts (like tabs, windows, or iframes) in the browser and may not be suitable for server-side use cases like Deno Deploy where instances may be running in completely separate environments. Regarding your question about the first instance disappearing, if you are relying on a single instance to always be available to broadcast the key, then yes, there is a strong assumption that this instance will not disappear. If it does, the other instances will not be able to receive the key. For sharing data between multiple instances in Deno Deploy, you might want to consider using a more persistent and reliable storage solution. Deno Deploy offers integration with Durable Objects, which can be used to manage state across instances. Alternatively, you could use an external database or a key-value store that is accessible from all instances. As for the code itself, I noticed a syntax error in the following line:
key = message.data,
key = message.data,
The comma at the end should be a semicolon to end the statement properly:
key = message.data;
key = message.data;
Remember to always test your code thoroughly and consider edge cases, such as what happens if the first instance fails or restarts. For a robust solution, you would typically use a persistent storage mechanism that is external to your application instances.
patrickalima98
patrickalima984mo ago
It's something I want to know too
Mark G
Mark G4mo ago
If it's just a one-off permanent key, you could just set it as an environment variable, and then all instances will have it.
Mark G
Mark G4mo ago
Otherwise you may want to consider setting it in kv, you should be able to make use of its transactional capability to ensure it's only set once. Or have a dedicated endpoint that you hit manually to initialize it after deployment. https://deno.com/kv
Deno
Deno KV - a global database for global apps
Deno KV is globally replicated low-latency key-value data storage at the edge. Build global apps with serverless computing with distributed key-value storage.
Mark G
Mark G4mo ago
In Deploy you must assume that all instances are transient. You can't rely on an actual instance as a means of central storage or distribution, all instances should be considered peers, and short lived.
foobar
foobar4mo ago
thanks for your answer and information on instance. The key is a new key at each deploy that I don't want to set as en env variable. I didn't want also call kv at each time I read the key (too much read on kv if I can avoid it). The new versions, agnostic to 1st instance
/**
* Channel for broadcasting key
*/
const channel = new BroadcastChannel("JWT_KEY");

let keyReceived = false;
let key = generateKey();

channel.onmessage = async (event: MessageEvent<Message>) => {
const message = event.data;
if (message.nature === "newinstance") {
// all instance send key
channel.postMessage({ nature: "key", data: key });
}
if (message.nature === "key" && !keyReceived) {
// only instance with keyReceived = false change key
keyReceived = true;
// new key
key = message.data;
}
};

/**
* All instance post the message
* if 1st instance => no onmessage (1:keyReceived = false )
* if 2nd instance => only 1st instance receive message => send key (1:keyReceived = false ; 2:keyReceived = true )
* if 3rd instance => all instance send message => first reponse received is good (1:keyReceived = true ; 2:keyReceived = true ; 3:keyReceived = true )
*/
channel.postMessage({ nature: "newinstance" });
/**
* Channel for broadcasting key
*/
const channel = new BroadcastChannel("JWT_KEY");

let keyReceived = false;
let key = generateKey();

channel.onmessage = async (event: MessageEvent<Message>) => {
const message = event.data;
if (message.nature === "newinstance") {
// all instance send key
channel.postMessage({ nature: "key", data: key });
}
if (message.nature === "key" && !keyReceived) {
// only instance with keyReceived = false change key
keyReceived = true;
// new key
key = message.data;
}
};

/**
* All instance post the message
* if 1st instance => no onmessage (1:keyReceived = false )
* if 2nd instance => only 1st instance receive message => send key (1:keyReceived = false ; 2:keyReceived = true )
* if 3rd instance => all instance send message => first reponse received is good (1:keyReceived = true ; 2:keyReceived = true ; 3:keyReceived = true )
*/
channel.postMessage({ nature: "newinstance" });