has anyone else ran into "Durable Object storage is no longer accessible" in tests?
has anyone else ran into "Durable Object storage is no longer accessible" in tests?
Specifically for Durable Object classes with SQLite storage backend, KV operations which were previously asynchronous (for example, get, put, delete, deleteAll, list) are synchronous, even though they return promises. These methods will have completed their operations before they return the promise.
runDurableObjectAlarm() return true or a similar value?while (true) what about while (ran)? Declare ran as true before the first runawait to be consistent with the API that you need to await a Promise. The underlying behavior doesn't change.await of a promise will be more confused, rather than having to read all the DO docs to figure out that it doesn't matter.blockConcurrencyWhile when applying migration in constructor, and also I can put the entire migration into a transactionSync to prevent the rare event that migrations succeeded but writing migration number fails.transaction()? blockConcurrencyWhile has a different purpose than sync/async.storage.get/storage.set's implementations are sync, because applyMigration is async, .then puts continuation in the next event loop, so the log order will be before -> after -> initialized. I haven't tested it but unless DO has a different behavior to regular JS, that should be the case.this.someState is still undefined) by the end of current event loop. I don't know if DO is able to process messages in the same event loop as the one doing the construction, but if that's true, then that's an issue.blockConcurrencyWhile is a workaround, but if we had an actual sync API, we wouldn't even need it.this.someState = -1 before the call to ctx.blockConcurrencyWhile(...) and then the property won't be considered optional.blockConcurrencyWhile at all, because applyMigrations can just be sync.storage.get/storage.set is async, you also couldn't do:await puts continuation in the next event loop, by which point transactionSync already exited.transaction(...) which is async. Anyway, we seem to be going in circles SELECT name FROM sqlite_master WHERE type='table' AND name=?;async function applyMigrations(storage: DurableObjectStorage) {
await storage.get(...)
// Do migration stuffs
await storage.set(...)
}class MyDO extends DurableObject {
someState!: number
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env)
console.log('before')
applyMigrations(ctx.storage).then(() => {
this.someState = 42
console.log('initialized')
})
console.log('after')
}
}async function applyMigrations(storage: DurableObjectStorage) {
storage.transactionSync(async () => {
const currentMigration = await storage.get(...)
// Do migration stuffs
await storage.set(...)
})
}let ran = false;
ran = await runDurableObjectAlarm(stub) // ran = true
ran = await runDurableObjectAlarm(stub) // ran = true
ran = await runDurableObjectAlarm(stub) // ran = true
ran = await runDurableObjectAlarm(stub) // ran = true
ran = await runDurableObjectAlarm(stub) // ran = falsewhile (true) {
let ran = await runDurableObjectAlarm(stub)
if (!ran) {
break
};
}runDurableObjectAlarm()await this.#_config.doStorage.put<number>(this.#_lastMigrationIDKeyName(), this.#_lastMigrationMonotonicId);