Run Task
One script reply has been approved by the moderators Verified

Runs an Actor Task. You can optionally override the Actor’s input configuration by providing a custom body.

Created by jakub.drobnik222 88 days ago Picked 14 times
Submitted by jakub.drobnik222 Bun
Verified 88 days ago
1
import { ApifyClient, Dictionary, TaskCallOptions } from 'apify-client@^2.19.0';
2

3
type ApifyApiKey = {
4
  api_key: string;
5
};
6

7
type Apify = {
8
  token: string;
9
};
10

11
type MemoryInMb =
12
  | '128'
13
  | '256'
14
  | '512'
15
  | '1024'
16
  | '2048'
17
  | '4096'
18
  | '8192'
19
  | '16384'
20
  | '32768';
21

22
export type DynSelect_taskId = string;
23
export async function taskId(api_key?: ApifyApiKey, oauth_token?: Apify) {
24
  if (!api_key?.api_key && !oauth_token?.token) {
25
    return [{ value: '', label: 'Missing Apify API key or OAuth token' }];
26
  }
27

28
  try {
29
    const client = createClient(api_key, oauth_token);
30

31
    const data = await client.tasks().list();
32
    const items = data?.items ?? [];
33

34
    return items.map((task: any) => ({
35
      value: task.id,
36
      label: task.title || task.name || task.id,
37
    }));
38
  } catch (error: any) {
39
    return [
40
      { value: '', label: `Failed to load tasks: ${error.message || error}` },
41
    ];
42
  }
43
}
44

45
const createClient = (api_key?: ApifyApiKey, oauth_token?: Apify): ApifyClient => {
46
  const token = oauth_token?.token ?? api_key?.api_key;
47
  if (!token) {
48
    throw new Error('Missing Apify API key or OAuth token');
49
  }
50

51
  return new ApifyClient({
52
    token: token,
53
    requestInterceptors: [
54
      (request) => {
55
        if (!request.headers) {
56
          request.headers = {};
57
        }
58
        request.headers['x-apify-integration-platform'] = 'windmill';
59
        return request;
60
      },
61
    ],
62
  });
63
};
64

65
async function pollRunStatus(
66
  client: ApifyClient,
67
  runId: string,
68
  options: { throwIfNotSucceeded: boolean; } = { throwIfNotSucceeded: false }
69
): Promise<any> {
70
  let status = '';
71
  let runData: any;
72
  while (true) {
73
    runData = await client.run(runId).get();
74
    status = runData.status;
75
    if (['SUCCEEDED', 'FAILED', 'ABORTED', 'TIMED-OUT'].includes(status)) break;
76
    await new Promise((res) => setTimeout(res, 1000));
77
  }
78

79
  if (options.throwIfNotSucceeded && status !== 'SUCCEEDED') {
80
    throw new Error(`Actor run did not succeed: ${status}`);
81
  }
82

83
  return runData;
84
}
85

86
export async function main(
87
  actorTaskId: DynSelect_taskId,
88
  customBody: object = {},
89
  timeout?: number | null,
90
  memoryInMb: MemoryInMb = '1024',
91
  build?: string,
92
  waitForFinish: boolean = true,
93
  api_key?: ApifyApiKey,
94
  oauth_token?: Apify,
95
) {
96
  if (!actorTaskId) {
97
    return { error: 'Task ID is required' };
98
  }
99

100
  const client = createClient(api_key, oauth_token);
101

102
  try {
103
    const runOptions: TaskCallOptions = {
104
      waitSecs: 0, // let custom logic handle the polling
105
    };
106

107
    if (timeout != null) runOptions.timeout = timeout;
108
    if (memoryInMb != null) runOptions.memory = Number(memoryInMb);
109
    if (build) runOptions.build = build;
110

111
    // Start the task run
112
    const apiResult = await client
113
      .task(actorTaskId)
114
      .call(customBody as Dictionary, runOptions);
115

116
    if (!apiResult?.id) {
117
      return { error: 'Run ID not found after running the task' };
118
    }
119

120
    if (!waitForFinish) {
121
      return { ...apiResult };
122
    }
123

124
    const runId = apiResult.id;
125
    const lastRunData = await pollRunStatus(client, runId);
126
    return { ...lastRunData };
127
  } catch (error: any) {
128
    return {
129
      error: `Failed to run task. Reason: ${error.message}`,
130
    };
131
  }
132
}
133