go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/static/_nextjs/src/api/workflow.ts (about)

     1  /**
     2   * Copyright (c) 2024 - Present. Will Charczuk. All rights reserved.
     3   * Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     4   */
     5  export interface WorkflowRunInfo {
     6    workflow_id: string;
     7    run_id: string;
     8  }
     9  
    10  export interface WorkflowRunFailureCause {
    11    message: string;
    12    source: string;
    13  }
    14  
    15  export interface WorkflowRunFailure {
    16    message: string;
    17    source: string;
    18    cause: WorkflowRunFailureCause
    19  }
    20  
    21  export interface WorkflowRunStatus {
    22    workflow_id: string
    23    run_id: string
    24    task_queue: string
    25    status: string
    26    start_time: Date
    27    close_time: Date
    28    failure?: WorkflowRunFailure
    29  }
    30  
    31  export async function stabilize(graphId: string, parallel: boolean): Promise<WorkflowRunInfo> {
    32    const res = await fetch(`/api/v1/graph/${graphId}/stabilize?${parallel ? 'parallel' : ''}`, {
    33      method: "POST",
    34    });
    35    if (!res?.ok) {
    36      const message = (await res.json()) as string;
    37      throw new Error(message)
    38    }
    39    const data = await res.json();
    40    return data as WorkflowRunInfo;
    41  };
    42  
    43  export async function getRunStatus(workflowId: string, runId: string): Promise<WorkflowRunStatus> {
    44    const res = await fetch(`/api/v1/workflow/${workflowId}/status/${runId}`, {
    45      method: "GET",
    46    });
    47    if (!res?.ok) {
    48      const message = (await res.json()) as string;
    49      throw new Error(message)
    50    }
    51    const data = await res.json();
    52    return data as WorkflowRunStatus;
    53  }
    54  
    55  const backoffs = [
    56    100, 100, 100, 100, 100, // 500ms
    57    500, // 1000ms
    58    1000, 1000, 1000, 1000, // 5000s
    59    5000, 5000, 5000, 5000, 5000, // 30s
    60    5000, 5000, 5000, 5000, 5000, 5000, // 60s
    61  ]
    62  
    63  export async function pollUntilFinished(workflowId: string, runId: string): Promise<WorkflowRunStatus> {
    64    let status = await getRunStatus(workflowId, runId);
    65    if (isFinished(status)) {
    66      return status
    67    }
    68  
    69    for (let attempt = 0; attempt < backoffs.length; attempt++) {
    70      await new Promise(f => setTimeout(f, backoffs[attempt]));
    71      status = await getRunStatus(workflowId, runId);
    72      if (isFinished(status)) {
    73        return status
    74      }
    75    }
    76    throw new Error("workflow execution timed out after 60 seconds");
    77  }
    78  
    79  function isFinished(runStatus: WorkflowRunStatus): boolean {
    80    return runStatus.status !== 'Unknown' && runStatus.status !== "Running"
    81  }