-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbatch_http_request.js
More file actions
106 lines (100 loc) · 3.29 KB
/
Copy pathbatch_http_request.js
File metadata and controls
106 lines (100 loc) · 3.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { NetsuiteApiClient } from "netsuite-api-client";
export default defineComponent({
name: "Batch NetSuite Request",
description: "Send a batch of requests to a single NetSuite REST API endpoint.",
key: "batch_netsuite_request",
type: "action",
// Unless urgently needed, this action should only be modified in Github
version: "0.1.1",
props: {
config: {
type: "string",
label: "NetSuite Config",
description: `NetSuite Configuration JSON object. In format, {"consumer_key":"...","consumer_secret_key":"...","token":"...","token_secret":"...","realm":"..."}`,
secret: true,
},
httpRequest: {
type: "http_request",
label: "HTTP Request",
description: "Request to make to Netsuite."
},
bodies: {
type: "string[]",
label: "Request Bodies",
description: "Request Bodies to send to NetSuite. Overrides `Body` from HTTP Request."
},
batchSize: {
type: "integer",
label: "Batch Size",
description: "Larger batch sizes may hit concurrent request limit. Defaults to `5`.",
optional: true,
default: 5
},
requestTimeout: {
type: "integer",
label: "Request timeout",
description: "The maximum number of milliseconds per request before timing out. Defaults to `30000`ms.",
min: 1,
default: 30000,
optional: true,
},
batchInterval: {
type: "integer",
label: "Batch Interval",
description: "The request loop will send each subsequent block of requests after no less than this amount of time since the previous block began. Set this according to rate limiting rules in effect for the host.",
optional: true,
default: 4000
},
},
methods: {
async request(client, body) {
await Promise.race([
client.request({
method: this.httpRequest.method,
path: this.httpRequest.url,
body: body,
headers: this.httpRequest.headers
}),
this.timeout(this.requestTimeout)
]);
},
timeout(ms) {
return new Promise((_, reject) =>
setTimeout(() => reject(new Error(`Request timeout after ${ms}ms`)), ms)
);
},
async delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
},
async run({ $ }) {
const config = JSON.parse(this.config)
console.log("Realm:", config.realm)
const client = new NetsuiteApiClient(config);
try {
const queue = [];
for (let i = 0; i < this.bodies.length; i++) {
queue.push(this.request(client, this.bodies[i]));
if (i > 0 && i % this.batchSize == 0) {
const now = Date.now();
await Promise.allSettled(queue);
const elapsed = Date.now() - now;
await this.delay(this.batchInterval - elapsed);
}
}
// TODO check queue for rejected items
const result = await Promise.allSettled(queue);
$.export("$summary", `${this.httpRequest.method} ${this.httpRequest.url} succeeded for ${this.bodies.length} items.`);
} catch (error) {
console.error(
"NetSuite API Error:",
error.response?.data || error.message
);
throw new Error(
`Failed to execute NetSuite request: ${
error.response?.data?.detail || error.message
}`
);
}
},
});