notes

Personal notes

Cloudflare Workflows

Ono se řekne: “Za týden vytvoř v účetním systému fakturu, PDF rozparsuj do HTML a pošli zákazníkovi e-mailem.”

Ale těch věcí, co se může pokazit!

Každý z těchto kroků se může pokazit, ale předchozí kroky nechceme opakovat. Vždyť každé to stažení z S3 něco stojí a volání AI na parsování faktur taky není zadarmo.

Nechci si ani představovat, co za šelmostroj to musí být. Naštěstí můžu použít Cloudflare Workflows (zatím veřejná Beta).

Co jsou Cloudflare Workflows

Workflows is a durable execution engine built on Cloudflare Workers. Workflows allow you to build multi-step applications that can automatically retry, persist state and run for minutes, hours, days, or weeks. Workflows introduces a programming model that makes it easier to build reliable, long-running tasks, observe as they progress, and programatically trigger instances based on events across your services.

dokumentace

Náš (naivní) příklad s fakturou

// naše faktura co chceme vystavit
type InvoiceParams = {
  data: any;
};

export class InvoiceWorkflow extends WorkflowEntrypoint<Env, InvoiceParams> {
  async run(event: WorkflowEvent<InvoiceParams>, step: WorkflowStep) {
    // Počkáme týden
    await step.sleep("wait for a week", "1 week");

    // Vytvoříme fakturu v účetním systému
    const invoice_url = await step.do(
      "create invoice",
      {
        retries: {
          limit: 10,
          delay: "10 seconds",
          backoff: "linear",
        },
        timeout: "30 minutes",
      },
      async () => {
        let response = await fetch("https://our.payment.system/invoices", {
          method: "POST",
          headers: {
            "Content-Type": "application/json; charset=utf-8",
          },
          body: JSON.stringify(event.payload.data),
        });

        if (response.status === 503) {
          // vyhozený Error nám zopakuje krok
          throw new Error("invoicing has failed, try again");
        }

        if (response.status === 418) {
          // vyhozený NonRetryableError nám ukončí celé Workflow
          throw new NonRetryableError("invoicing has unknown status, don't try again");
        }

        return response.headers.get("Location");
      },
    );

    // Stáhneme fakturu
    const invoice = await step.do("fetch invoice", {/* options */ }, async () => {
      console.log(`fetch invoice from URL ${invoice_url}`);
      //...
    });

    // Stáhneme PDF z S3
    const pdf = await step.do("download PDF", ...);

    // Parsujeme PDF pomocí AI
    const parsed_invoice = await step.do("parse PDF", ...);

    // A nakonec odesíláme fakturu zákazníkovi
    await step.do("send e-mail with invoice", ...);
  }
}