Skip to content

[TRI-1008] Add io.waitUntil function to allow a job run to wait for a dynamic condition #315

@ericallam

Description

@ericallam

This kind of thing would be really useful in jobs:

await io.waitUntil("has used invite", {
  condition: async () => {
    const user = await prisma.user.findUniqueOrThrow({
      where: {
        id: payload.userId,
      },
    });

    return user.invitationCodeId !== null;
  },
});

This would basically retry the condition function in an interval, and only continue once the condition function returned true.

The strategy for how frequent to call the condition function could be configurable:

  • Set an interval frequency (minimum would be 60 seconds, max would be 1 day). Would also need some kind of timeout thing like "exit if the condition doesn't return true within 30 days"
  • Set an exponential backoff strategy (similar to our task retries) with a maximum of 25 retries

This can be achieved using only subtasks and io.wait, something like:

type WaitUntilOptions = {
  condition: () => Promise<boolean>;
  checkInterval?: number;
};

function waitUntil(
  key: string,
  io: IO,
  options: WaitUntilOptions
): Promise<void> {
  return io.runTask(
    key,
    {
      name: "Wait until",
    },
    async (task) => {
      const result = await options.condition();
      if (result) return;

      //if more than 14 days has passed then throw
      const startedAt = task.startedAt;
      if (!startedAt) return;
      const now = new Date();
      const diff = now.getTime() - startedAt.getTime();
      const days = diff / (1000 * 60 * 60 * 24);
      if (days > 14) {
        throw new Error(
          `Waited for 14 days for condition to be true but it never was.`
        );
      }

      await io.wait(
        `${key}:${new Date().toISOString()}`,
        options.checkInterval ? Math.max(options.checkInterval, 30) : 60 * 60
      );
    }
  );
}

But i'd prefer this not to produce a bunch of tasks that are only there for the interval.

TRI-1008

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/docsarea/serverIssues related to the Trigger.dev serverenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions