cloudflare / miniflare

🔥 Fully-local simulator for Cloudflare Workers. For the latest version, see https://github.com/cloudflare/workers-sdk/tree/main/packages/miniflare.
https://miniflare.dev
MIT License
3.78k stars 205 forks source link

Trigger a DO alarm in miniflare@3 #626

Closed SamyPesse closed 1 year ago

SamyPesse commented 1 year ago

Since miniflare@3 uses workerd, there is no more direct interfaces with the DO storage, previously to trigger an alarm in my unit test, I was writing:

durableObjectStorage.setAlarm(Date.now());

I understand why now it's not possible to do this, but I'm curious if there is a hack or an alternative? Testing DO alarms is important in unit tests and we can't wait for it to trigger in N minutes/hours. A solution could be to have a condition to trigger after 1sec when I detect it's miniflare, but I don't always want the alarm to trigger right away.

mrbbot commented 1 year ago

Hey! 👋 For now, I'd probably add a special endpoint to your Durable Object for running its alarm. You could just have this enabled when you detect Miniflare.

export class DurableObject {
  async fetch(request) {
    if (request.cf?.alarm) {
      await this.alarm();
      return new Response();
    }
    ...
  }

  async alarm() {}
}

export default {
  async fetch(request, env, ctx) {
    ...
    const id = env.OBJECT.newUniqueId();
    const stub = env.OBJECT.get(id);
    return stub.fetch("http://localhost", { cf: { alarm: true } });
  }
}

We're also considering adding back deprecated support for Miniflare#getDurableObjectNamespace() too.

SamyPesse commented 1 year ago

Thank you, it matches the solution I've opted for, it works for now :)

mrbbot commented 1 year ago

Going to close this issue as I think the suggest workaround works well. 👍 We did add back Miniflare#getDurableObjectNamespace() so this can be simplified to...

export class DurableObject {
  async fetch(request) {
    if (request.cf?.alarm) {
      await this.alarm();
      return new Response();
    }
    ...
  }

  async alarm() {}
}

// ...then in your Node script...

const mf = new Miniflare({
  durableObjects: { OBJECT: "DurableObject" },
  ...
});
const ns = await mf.getDurableObjectNamespace("OBJECT");
const id = ns.newUniqueId();
const stub = ns.get(id);
return stub.fetch("http://localhost", { cf: { alarm: true } });