@platforma-sdk/workflow-tengo 4.6.5 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tengo/lib/exec.constants.lib.tengo +6 -2
- package/dist/tengo/lib/exec.lib.tengo +9 -6
- package/dist/tengo/lib/exec.limits.lib.tengo +38 -13
- package/dist/tengo/lib/exec.runcmd.lib.tengo +35 -23
- package/dist/tengo/lib/feats.lib.tengo +15 -0
- package/dist/tengo/lib/tpl.base.lib.tengo +3 -0
- package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
- package/dist/tengo/tpl/exec.R.create-renv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
- package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
- package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
- package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
- package/package.json +1 -1
|
@@ -1,21 +1,25 @@
|
|
|
1
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
2
|
+
|
|
1
3
|
ARG_TYPE_STRING := "string"
|
|
2
4
|
ARG_TYPE_EXPRESSION := "expressionRef"
|
|
3
5
|
ARG_TYPE_VAR := "variableRef" // TODO: deprecated, remove after 15 Mar 2025
|
|
4
6
|
ARG_TYPES := [ARG_TYPE_STRING, ARG_TYPE_EXPRESSION, ARG_TYPE_VAR]
|
|
5
7
|
|
|
8
|
+
BATCH_QUEUE := "batch" // special queue in storage controller with no limits
|
|
6
9
|
HEAVY_QUEUE := "heavy"
|
|
7
10
|
MEDIUM_QUEUE := "medium"
|
|
8
11
|
LIGHT_QUEUE := "light"
|
|
9
12
|
UI_TASKS_QUEUE := "ui-tasks"
|
|
10
13
|
|
|
11
|
-
export {
|
|
14
|
+
export ll.toStrict({
|
|
12
15
|
ARG_TYPE_STRING: ARG_TYPE_STRING,
|
|
13
16
|
ARG_TYPE_EXPRESSION: ARG_TYPE_EXPRESSION,
|
|
14
17
|
ARG_TYPE_VAR: ARG_TYPE_VAR,
|
|
15
18
|
ARG_TYPES: ARG_TYPES,
|
|
16
19
|
|
|
20
|
+
BATCH_QUEUE: BATCH_QUEUE,
|
|
17
21
|
UI_TASKS_QUEUE: UI_TASKS_QUEUE,
|
|
18
22
|
LIGHT_QUEUE: LIGHT_QUEUE,
|
|
19
23
|
MEDIUM_QUEUE: MEDIUM_QUEUE,
|
|
20
24
|
HEAVY_QUEUE: HEAVY_QUEUE
|
|
21
|
-
}
|
|
25
|
+
})
|
|
@@ -759,12 +759,15 @@ builder := func() {
|
|
|
759
759
|
}
|
|
760
760
|
|
|
761
761
|
serviceExecInputs := {}
|
|
762
|
-
if feats.workdirLimits || feats.computeLimits {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
762
|
+
if feats.workdirLimits || feats.computeLimits || limits.useBatch(queue) {
|
|
763
|
+
if (is_int(ramRequest)) {
|
|
764
|
+
ramRequest = string(ramRequest) + "b"
|
|
765
|
+
}
|
|
766
|
+
serviceExecInputs.quota = {
|
|
767
|
+
queue: queue,
|
|
768
|
+
cpu: cpuRequest,
|
|
769
|
+
ram: ramRequest
|
|
770
|
+
}
|
|
768
771
|
}
|
|
769
772
|
|
|
770
773
|
|
|
@@ -9,8 +9,11 @@ ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
|
9
9
|
|
|
10
10
|
oop := import("@platforma-sdk/workflow-tengo:oop")
|
|
11
11
|
validation := import("@platforma-sdk/workflow-tengo:validation")
|
|
12
|
+
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
12
13
|
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
13
14
|
json := import("json")
|
|
15
|
+
constants := import("@platforma-sdk/workflow-tengo:exec.constants")
|
|
16
|
+
feats := import("@platforma-sdk/workflow-tengo:feats")
|
|
14
17
|
|
|
15
18
|
_RTYPE_QUOTA := { Name: "Quota", Version: "1" }
|
|
16
19
|
|
|
@@ -19,6 +22,16 @@ _RTYPE_QUOTA := { Name: "Quota", Version: "1" }
|
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
|
|
25
|
+
|
|
26
|
+
useBatch := func(queueName) {
|
|
27
|
+
return feats.hasBatch && !slices.hasElement([ constants.UI_TASKS_QUEUE ], queueName)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
22
35
|
quotaBuilder := func() {
|
|
23
36
|
self := undefined
|
|
24
37
|
|
|
@@ -132,9 +145,11 @@ storageSpaceRequestBuilder := func() {
|
|
|
132
145
|
requestBuilder := smart.ephemeralBuilder(_RTYPE_STORAGE_SPACE_REQUEST)
|
|
133
146
|
requestBuilder.getField(_SSR_FIELD_REQUEST).set(quota)
|
|
134
147
|
|
|
148
|
+
requestRef := requestBuilder.lockAndBuild()
|
|
149
|
+
|
|
135
150
|
return ll.toStrict(
|
|
136
|
-
oop.inherit(
|
|
137
|
-
allocation:
|
|
151
|
+
oop.inherit(requestRef, {
|
|
152
|
+
allocation: requestRef.getField(_SSR_FIELD_ALLOCATION)
|
|
138
153
|
})
|
|
139
154
|
)
|
|
140
155
|
}
|
|
@@ -143,8 +158,9 @@ storageSpaceRequestBuilder := func() {
|
|
|
143
158
|
return self
|
|
144
159
|
}
|
|
145
160
|
|
|
146
|
-
|
|
147
|
-
|
|
161
|
+
_RTYPE_COMPUTE_REQUEST_EXECUTOR_V1 := { Name: "ComputeRequest/executor", Version: "1" }
|
|
162
|
+
_RTYPE_COMPUTE_REQUEST_BATCH_V1 := { Name: "ComputeRequest/batch", Version: "1" }
|
|
163
|
+
|
|
148
164
|
_CR_FIELD_REQUEST := "request" // input
|
|
149
165
|
_CR_FIELD_ALLOCATION := "allocation" // output
|
|
150
166
|
|
|
@@ -152,7 +168,7 @@ computeRequestBuilder := func() {
|
|
|
152
168
|
self := undefined
|
|
153
169
|
|
|
154
170
|
quota := undefined
|
|
155
|
-
|
|
171
|
+
queue_name := undefined
|
|
156
172
|
|
|
157
173
|
self = ll.toStrict({
|
|
158
174
|
|
|
@@ -173,10 +189,9 @@ computeRequestBuilder := func() {
|
|
|
173
189
|
|
|
174
190
|
|
|
175
191
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
executor = execID
|
|
192
|
+
queue: func(name) {
|
|
193
|
+
validation.assertType(name, "string", "exec.limits.queue: queue name should be a string")
|
|
194
|
+
queue_name = name
|
|
180
195
|
|
|
181
196
|
return self
|
|
182
197
|
},
|
|
@@ -188,14 +203,23 @@ computeRequestBuilder := func() {
|
|
|
188
203
|
|
|
189
204
|
build: func() {
|
|
190
205
|
ll.assert(smart.isReference(quota), "exec.limits.build: quota of ComputeRequest must be a valid reference")
|
|
206
|
+
ll.assert(queue_name != "", "exec.limits.build: queue name is required for computeRequestBuilder")
|
|
207
|
+
|
|
208
|
+
requestBuilder := undefined
|
|
209
|
+
|
|
210
|
+
if useBatch(queue_name) {
|
|
211
|
+
requestBuilder = smart.ephemeralBuilder(_RTYPE_COMPUTE_REQUEST_BATCH_V1)
|
|
212
|
+
} else {
|
|
213
|
+
requestBuilder = smart.ephemeralBuilder(_RTYPE_COMPUTE_REQUEST_EXECUTOR_V1)
|
|
214
|
+
}
|
|
191
215
|
|
|
192
|
-
rType := _RTYPE_COMPUTE_REQUEST(executor)
|
|
193
|
-
requestBuilder := smart.ephemeralBuilder(rType)
|
|
194
216
|
requestBuilder.getField(_CR_FIELD_REQUEST).set(quota)
|
|
195
217
|
|
|
218
|
+
requestRef := requestBuilder.lockAndBuild()
|
|
219
|
+
|
|
196
220
|
return ll.toStrict(
|
|
197
|
-
oop.inherit(
|
|
198
|
-
allocation:
|
|
221
|
+
oop.inherit(requestRef, {
|
|
222
|
+
allocation: requestRef.getField(_CR_FIELD_ALLOCATION)
|
|
199
223
|
})
|
|
200
224
|
)
|
|
201
225
|
}
|
|
@@ -205,6 +229,7 @@ computeRequestBuilder := func() {
|
|
|
205
229
|
}
|
|
206
230
|
|
|
207
231
|
export ll.toStrict({
|
|
232
|
+
useBatch: useBatch,
|
|
208
233
|
quotaBuilder: quotaBuilder,
|
|
209
234
|
storageSpaceRequestBuilder: storageSpaceRequestBuilder,
|
|
210
235
|
computeRequestBuilder: computeRequestBuilder
|
|
@@ -15,7 +15,8 @@ slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
|
15
15
|
limits := import("@platforma-sdk/workflow-tengo:exec.limits")
|
|
16
16
|
|
|
17
17
|
_RTYPE_RUN_COMMAND_V1 := { Name: "RunCommand/executor", Version: "1" }
|
|
18
|
-
|
|
18
|
+
_RTYPE_RUN_COMMAND_EXEC_V2 := { Name: "RunCommand/executor", Version: "2" }
|
|
19
|
+
_RTYPE_RUN_COMMAND_BATCH_V2 := { Name: "RunCommand/batch", Version: "2" }
|
|
19
20
|
_RTYPE_RUN_COMMAND_CMD := { Name: "RunCommandCmd", Version: "1" }
|
|
20
21
|
_RTYPE_RUN_COMMAND_ARGS := { Name: "RunCommandArgs", Version: "1" }
|
|
21
22
|
_RTYPE_RUN_COMMAND_OPTIONS := { Name: "run-command/options", Version: "1" }
|
|
@@ -77,16 +78,6 @@ _createExpressionArg := func(argTpl) {
|
|
|
77
78
|
|
|
78
79
|
|
|
79
80
|
builder := func(workdir) {
|
|
80
|
-
res := undefined
|
|
81
|
-
|
|
82
|
-
if feats.computeLimits {
|
|
83
|
-
res = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_V2)
|
|
84
|
-
} else {
|
|
85
|
-
res = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_V1)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
res.getField(_FIELD_WORKDIR_IN).set(workdir)
|
|
89
|
-
|
|
90
81
|
self := undefined
|
|
91
82
|
|
|
92
83
|
cmd := undefined
|
|
@@ -105,7 +96,7 @@ builder := func(workdir) {
|
|
|
105
96
|
stderr := "stderr.txt"
|
|
106
97
|
nErrorLines := 200
|
|
107
98
|
|
|
108
|
-
self = ll.toStrict(
|
|
99
|
+
self = ll.toStrict({
|
|
109
100
|
|
|
110
101
|
|
|
111
102
|
|
|
@@ -387,6 +378,25 @@ builder := func(workdir) {
|
|
|
387
378
|
|
|
388
379
|
|
|
389
380
|
build: func() {
|
|
381
|
+
runRes := undefined
|
|
382
|
+
|
|
383
|
+
useBatch := limits.useBatch(queue)
|
|
384
|
+
|
|
385
|
+
if useBatch {
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
runRes = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_BATCH_V2)
|
|
390
|
+
|
|
391
|
+
} else if feats.computeLimits {
|
|
392
|
+
runRes = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_EXEC_V2)
|
|
393
|
+
|
|
394
|
+
} else {
|
|
395
|
+
runRes = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_V1)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
runRes.getField(_FIELD_WORKDIR_IN).set(workdir)
|
|
399
|
+
|
|
390
400
|
|
|
391
401
|
|
|
392
402
|
ll.assert(!hasPatternArgs || len(substRules) != 0,
|
|
@@ -396,21 +406,23 @@ builder := func(workdir) {
|
|
|
396
406
|
"runcmd.builder().build: expression arguments must be enabled only if platforma backend supports expressions, found: %v",
|
|
397
407
|
hasExpressionArgs)
|
|
398
408
|
|
|
399
|
-
if feats.computeLimits {
|
|
409
|
+
if feats.computeLimits || useBatch {
|
|
400
410
|
if !smart.isReference(_allocation) {
|
|
401
411
|
|
|
402
412
|
|
|
403
|
-
|
|
404
|
-
|
|
413
|
+
_quotaRef := limits.quotaBuilder().queue(queue).build()
|
|
414
|
+
_resReqRef := limits.computeRequestBuilder().queue(queue).quota(_quotaRef).build()
|
|
415
|
+
_allocation = _resReqRef.allocation
|
|
405
416
|
}
|
|
406
|
-
|
|
417
|
+
|
|
418
|
+
runRes.getField(_FIELD_ALLOCATION).set(_allocation)
|
|
407
419
|
}
|
|
408
420
|
|
|
409
421
|
refsRes := smart.createMapResourceWithType(_RTYPE_RUN_COMMAND_REFS, refs)
|
|
410
|
-
|
|
422
|
+
runRes.getField(_FIELD_REFS).set(refsRes)
|
|
411
423
|
|
|
412
424
|
cmdRes := smart.createValueResource(_RTYPE_RUN_COMMAND_CMD, json.encode(cmd))
|
|
413
|
-
|
|
425
|
+
runRes.getField(_FIELD_CMD).set(cmdRes)
|
|
414
426
|
|
|
415
427
|
options := {
|
|
416
428
|
queueName: queue,
|
|
@@ -423,19 +435,19 @@ builder := func(workdir) {
|
|
|
423
435
|
}
|
|
424
436
|
|
|
425
437
|
optionsRes := smart.createValueResource(_RTYPE_RUN_COMMAND_OPTIONS, json.encode(options))
|
|
426
|
-
|
|
438
|
+
runRes.getField(_FIELD_OPTIONS).set(optionsRes)
|
|
427
439
|
|
|
428
440
|
argsRes := smart.createValueResource(_RTYPE_RUN_COMMAND_ARGS, json.encode(args))
|
|
429
|
-
|
|
441
|
+
runRes.getField(_FIELD_ARGS).set(argsRes)
|
|
430
442
|
|
|
431
|
-
res := ll.toStrict(oop.inherit(
|
|
432
|
-
"workdir":
|
|
443
|
+
res := ll.toStrict(oop.inherit(runRes.lockAndBuild(), {
|
|
444
|
+
"workdir": runRes.outputs()[_FIELD_WORKDIR_OUT],
|
|
433
445
|
"options": options
|
|
434
446
|
}))
|
|
435
447
|
|
|
436
448
|
return res
|
|
437
449
|
}
|
|
438
|
-
})
|
|
450
|
+
})
|
|
439
451
|
|
|
440
452
|
return self
|
|
441
453
|
}
|
|
@@ -18,7 +18,22 @@ _isEnabled := func(featName) {
|
|
|
18
18
|
return _checker(featName)
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
_executors := undefined
|
|
22
|
+
_hasRunner := func(e_id) {
|
|
23
|
+
if is_undefined(_executors) {
|
|
24
|
+
_executors = {}
|
|
25
|
+
for e in plapi.getExecutors() {
|
|
26
|
+
_executors[e] = true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return !is_undefined(_executors[e_id])
|
|
31
|
+
}
|
|
32
|
+
|
|
21
33
|
export ll.toStrict({
|
|
34
|
+
hasExec: _hasRunner("executor"), // local binary execution is available
|
|
35
|
+
hasBatch: _hasRunner("batch"), // batch system execution is available
|
|
36
|
+
|
|
22
37
|
pureFutureFields: _isEnabled("pureFutureFields") || _api >= 1, // 'pure' future fields magic that provides deduplication
|
|
23
38
|
commandExpressions: _isEnabled("commandExpressions") || _api >= 2, // rich expressions in command arguments ( {{ system.ram_bytes / 20 }} )
|
|
24
39
|
workdirLimits: _isEnabled("workdirLimits") || _api >= 4, // workdir storage controller can limit concurrency
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|