@budibase/server 2.6.19-alpha.30 → 2.6.19-alpha.34

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.
@@ -8,8 +8,8 @@
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
10
10
  rel="stylesheet" />
11
- <script type="module" crossorigin src="/builder/assets/index.3dd3d237.js"></script>
12
- <link rel="stylesheet" href="/builder/assets/index.8469b14c.css">
11
+ <script type="module" crossorigin src="/builder/assets/index.b6e30d5b.js"></script>
12
+ <link rel="stylesheet" href="/builder/assets/index.a96c516c.css">
13
13
  </head>
14
14
 
15
15
  <body id="app">
@@ -128,6 +128,7 @@ var init_environment = __esm({
128
128
  ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
129
129
  SELF_HOSTED: process.env.SELF_HOSTED,
130
130
  HTTP_MB_LIMIT: process.env.HTTP_MB_LIMIT,
131
+ FORKED_PROCESS_NAME: process.env.FORKED_PROCESS_NAME || "main",
131
132
  // old
132
133
  CLIENT_ID: process.env.CLIENT_ID,
133
134
  _set(key, value) {
@@ -3440,9 +3441,76 @@ var init_users3 = __esm({
3440
3441
  // ../backend-core/src/redis/redlockImpl.ts
3441
3442
  var redlockImpl_exports = {};
3442
3443
  __export(redlockImpl_exports, {
3443
- doWithLock: () => doWithLock
3444
+ doWithLock: () => doWithLock,
3445
+ newRedlock: () => newRedlock
3444
3446
  });
3445
- var import_redlock, getClient, OPTIONS, newRedlock, doWithLock;
3447
+ async function getClient(type, opts) {
3448
+ if (type === "custom" /* CUSTOM */) {
3449
+ return newRedlock(opts);
3450
+ }
3451
+ if (environment_default2.isTest() && type !== "try_once" /* TRY_ONCE */) {
3452
+ return newRedlock(OPTIONS.TEST);
3453
+ }
3454
+ switch (type) {
3455
+ case "try_once" /* TRY_ONCE */: {
3456
+ return newRedlock(OPTIONS.TRY_ONCE);
3457
+ }
3458
+ case "try_twice" /* TRY_TWICE */: {
3459
+ return newRedlock(OPTIONS.TRY_TWICE);
3460
+ }
3461
+ case "default" /* DEFAULT */: {
3462
+ return newRedlock(OPTIONS.DEFAULT);
3463
+ }
3464
+ case "delay_500" /* DELAY_500 */: {
3465
+ return newRedlock(OPTIONS.DELAY_500);
3466
+ }
3467
+ default: {
3468
+ throw new Error(`Could not get redlock client: ${type}`);
3469
+ }
3470
+ }
3471
+ }
3472
+ async function newRedlock(opts = {}) {
3473
+ let options2 = { ...OPTIONS.DEFAULT, ...opts };
3474
+ const redisWrapper = await getLockClient();
3475
+ const client3 = redisWrapper.getClient();
3476
+ return new import_redlock.default([client3], options2);
3477
+ }
3478
+ function getLockName(opts) {
3479
+ const prefix = opts.systemLock ? "system" : getTenantId();
3480
+ let name = `lock:${prefix}_${opts.name}`;
3481
+ if (opts.resource) {
3482
+ name = name + `_${opts.resource}`;
3483
+ }
3484
+ return name;
3485
+ }
3486
+ async function doWithLock(opts, task) {
3487
+ const redlock = await getClient(opts.type, opts.customOptions);
3488
+ let lock;
3489
+ try {
3490
+ const name = getLockName(opts);
3491
+ lock = await redlock.lock(name, opts.ttl);
3492
+ const result = await task();
3493
+ return { executed: true, result };
3494
+ } catch (e) {
3495
+ console.warn("lock error");
3496
+ if (e.name === "LockError") {
3497
+ if (opts.type === "try_once" /* TRY_ONCE */) {
3498
+ return { executed: false };
3499
+ } else {
3500
+ console.error(e);
3501
+ throw e;
3502
+ }
3503
+ } else {
3504
+ console.error(e);
3505
+ throw e;
3506
+ }
3507
+ } finally {
3508
+ if (lock) {
3509
+ await lock.unlock();
3510
+ }
3511
+ }
3512
+ }
3513
+ var import_redlock, OPTIONS;
3446
3514
  var init_redlockImpl = __esm({
3447
3515
  "../backend-core/src/redis/redlockImpl.ts"() {
3448
3516
  import_redlock = __toESM(require("redlock"));
@@ -3450,33 +3518,14 @@ var init_redlockImpl = __esm({
3450
3518
  init_src();
3451
3519
  init_context2();
3452
3520
  init_environment3();
3453
- getClient = async (type, opts) => {
3454
- if (type === "custom" /* CUSTOM */) {
3455
- return newRedlock(opts);
3456
- }
3457
- if (environment_default2.isTest() && type !== "try_once" /* TRY_ONCE */) {
3458
- return newRedlock(OPTIONS.TEST);
3459
- }
3460
- switch (type) {
3461
- case "try_once" /* TRY_ONCE */: {
3462
- return newRedlock(OPTIONS.TRY_ONCE);
3463
- }
3464
- case "default" /* DEFAULT */: {
3465
- return newRedlock(OPTIONS.DEFAULT);
3466
- }
3467
- case "delay_500" /* DELAY_500 */: {
3468
- return newRedlock(OPTIONS.DELAY_500);
3469
- }
3470
- default: {
3471
- throw new Error(`Could not get redlock client: ${type}`);
3472
- }
3473
- }
3474
- };
3475
3521
  OPTIONS = {
3476
3522
  TRY_ONCE: {
3477
3523
  // immediately throws an error if the lock is already held
3478
3524
  retryCount: 0
3479
3525
  },
3526
+ TRY_TWICE: {
3527
+ retryCount: 1
3528
+ },
3480
3529
  TEST: {
3481
3530
  // higher retry count in unit tests
3482
3531
  // due to high contention.
@@ -3503,44 +3552,6 @@ var init_redlockImpl = __esm({
3503
3552
  retryDelay: 500
3504
3553
  }
3505
3554
  };
3506
- newRedlock = async (opts = {}) => {
3507
- let options2 = { ...OPTIONS.DEFAULT, ...opts };
3508
- const redisWrapper = await getLockClient();
3509
- const client3 = redisWrapper.getClient();
3510
- return new import_redlock.default([client3], options2);
3511
- };
3512
- doWithLock = async (opts, task) => {
3513
- const redlock = await getClient(opts.type, opts.customOptions);
3514
- let lock;
3515
- try {
3516
- const prefix = opts.systemLock ? "system" : getTenantId();
3517
- let name = `lock:${prefix}_${opts.name}`;
3518
- if (opts.resource) {
3519
- name = name + `_${opts.resource}`;
3520
- }
3521
- lock = await redlock.lock(name, opts.ttl);
3522
- const result = await task();
3523
- return { executed: true, result };
3524
- } catch (e) {
3525
- console.warn("lock error");
3526
- if (e.name === "LockError") {
3527
- if (opts.type === "try_once" /* TRY_ONCE */) {
3528
- console.warn(e);
3529
- return { executed: false };
3530
- } else {
3531
- console.error(e);
3532
- throw e;
3533
- }
3534
- } else {
3535
- console.error(e);
3536
- throw e;
3537
- }
3538
- } finally {
3539
- if (lock) {
3540
- await lock.unlock();
3541
- }
3542
- }
3543
- };
3544
3555
  }
3545
3556
  });
3546
3557
 
@@ -3647,6 +3658,7 @@ var init_logger = __esm({
3647
3658
  }
3648
3659
  const mergingObject = {
3649
3660
  err: error,
3661
+ pid: process.pid,
3650
3662
  ...contextObject
3651
3663
  };
3652
3664
  if (objects.length) {
@@ -26770,8 +26782,10 @@ function makeVariableKey(queryId, variable) {
26770
26782
  }
26771
26783
  function threadSetup() {
26772
26784
  if (environment_default.isTest() || environment_default.DISABLE_THREADING || !environment_default.isInThread()) {
26785
+ console.debug(`[${environment_default.FORKED_PROCESS_NAME}] thread setup skipped`);
26773
26786
  return;
26774
26787
  }
26788
+ console.debug(`[${environment_default.FORKED_PROCESS_NAME}] thread setup running`);
26775
26789
  init8();
26776
26790
  }
26777
26791
  async function checkCacheForDynamicVariable(queryId, variable) {
@@ -26845,13 +26859,17 @@ var _Thread = class {
26845
26859
  this.count = opts.count ? opts.count : 1;
26846
26860
  this.disableThreading = this.shouldDisableThreading();
26847
26861
  if (!this.disableThreading) {
26862
+ console.debug(
26863
+ `[${environment_default.FORKED_PROCESS_NAME}] initialising worker farm type=${type}`
26864
+ );
26848
26865
  const workerOpts = {
26849
26866
  autoStart: true,
26850
26867
  maxConcurrentWorkers: this.count,
26851
26868
  workerOptions: {
26852
26869
  env: {
26853
26870
  ...process.env,
26854
- FORKED_PROCESS: "1"
26871
+ FORKED_PROCESS: "1",
26872
+ FORKED_PROCESS_NAME: type
26855
26873
  }
26856
26874
  }
26857
26875
  };
@@ -26861,6 +26879,10 @@ var _Thread = class {
26861
26879
  }
26862
26880
  this.workers = (0, import_worker_farm.default)(workerOpts, typeToFile(type), ["execute"]);
26863
26881
  _Thread.workerRefs.push(this.workers);
26882
+ } else {
26883
+ console.debug(
26884
+ `[${environment_default.FORKED_PROCESS_NAME}] skipping worker farm type=${type}`
26885
+ );
26864
26886
  }
26865
26887
  }
26866
26888
  shouldDisableThreading() {
@@ -26872,9 +26894,7 @@ var _Thread = class {
26872
26894
  function fire(worker) {
26873
26895
  worker.execute(job, (err, response2) => {
26874
26896
  if (err && err.type === "TimeoutError") {
26875
- reject(
26876
- new Error(`Query response time exceeded ${timeout2}ms timeout.`)
26877
- );
26897
+ reject(new Error(`Thread timeout exceeded ${timeout2}ms timeout.`));
26878
26898
  } else if (err) {
26879
26899
  reject(err);
26880
26900
  } else {
@@ -31950,10 +31970,29 @@ init_constants6();
31950
31970
  init_environment();
31951
31971
  init_src4();
31952
31972
  init_src2();
31973
+ var import_object_sizeof = __toESM(require("object-sizeof"));
31974
+ var MAX_LOG_SIZE_MB = 5;
31975
+ var MB_IN_BYTES = 1024 * 1024;
31976
+ function sanitiseResults(results) {
31977
+ const message = `[removed] - max results size of ${MAX_LOG_SIZE_MB}MB exceeded`;
31978
+ for (let step of results.steps) {
31979
+ step.inputs = {
31980
+ message
31981
+ };
31982
+ step.outputs = {
31983
+ message,
31984
+ success: step.outputs.success
31985
+ };
31986
+ }
31987
+ }
31953
31988
  async function storeLog2(automation, results) {
31954
31989
  if (environment_default.DISABLE_AUTOMATION_LOGS) {
31955
31990
  return;
31956
31991
  }
31992
+ const bytes = (0, import_object_sizeof.default)(results);
31993
+ if (bytes / MB_IN_BYTES > MAX_LOG_SIZE_MB) {
31994
+ sanitiseResults(results);
31995
+ }
31957
31996
  await automations_exports.logs.storeLog(automation, results);
31958
31997
  }
31959
31998
 
@@ -31962,6 +32001,7 @@ init_src();
31962
32001
  init_src2();
31963
32002
  var import_string_templates8 = __toESM(require_src2());
31964
32003
  var import_fp8 = require("lodash/fp");
32004
+ var import_perf_hooks2 = require("perf_hooks");
31965
32005
  init_utils15();
31966
32006
  init_environment();
31967
32007
  utils_default.threadSetup();
@@ -31969,8 +32009,8 @@ var FILTER_STEP_ID = BUILTIN_ACTION_DEFINITIONS.FILTER.stepId;
31969
32009
  var LOOP_STEP_ID = BUILTIN_ACTION_DEFINITIONS.LOOP.stepId;
31970
32010
  var CRON_STEP_ID2 = definitions.CRON.stepId;
31971
32011
  var STOPPED_STATUS = { success: true, status: "stopped" /* STOPPED */ };
31972
- function getLoopIterations(loopStep, input) {
31973
- const binding = typecastForLooping(loopStep, input);
32012
+ function getLoopIterations(loopStep) {
32013
+ let binding = loopStep.inputs.binding;
31974
32014
  if (!binding) {
31975
32015
  return 0;
31976
32016
  }
@@ -31986,7 +32026,6 @@ var Orchestrator = class {
31986
32026
  constructor(job) {
31987
32027
  let automation = job.data.automation;
31988
32028
  let triggerOutput = job.data.event;
31989
- let timeout2 = job.data.event.timeout;
31990
32029
  const metadata = triggerOutput.metadata;
31991
32030
  this._chainCount = metadata ? metadata.automationChainCount : 0;
31992
32031
  this._appId = triggerOutput.appId;
@@ -32120,7 +32159,7 @@ var Orchestrator = class {
32120
32159
  });
32121
32160
  }
32122
32161
  async execute() {
32123
- var _a;
32162
+ var _a, _b;
32124
32163
  this._context.env = await getEnvironmentVariables2();
32125
32164
  let automation = this._automation;
32126
32165
  let stopped = false;
@@ -32139,6 +32178,7 @@ var Orchestrator = class {
32139
32178
  return;
32140
32179
  }
32141
32180
  }
32181
+ const start2 = import_perf_hooks2.performance.now();
32142
32182
  for (let step of automation.definition.steps) {
32143
32183
  if (timeoutFlag) {
32144
32184
  break;
@@ -32157,20 +32197,16 @@ var Orchestrator = class {
32157
32197
  }
32158
32198
  if (loopStep) {
32159
32199
  input = await (0, import_string_templates8.processObject)(loopStep.inputs, this._context);
32160
- iterations = getLoopIterations(loopStep, input);
32200
+ iterations = getLoopIterations(loopStep);
32161
32201
  }
32162
32202
  for (let index2 = 0; index2 < iterations; index2++) {
32163
32203
  let originalStepInput = (0, import_fp8.cloneDeep)(step.inputs);
32164
32204
  if (loopStep && input.binding) {
32165
- let newInput = await (0, import_string_templates8.processObject)(
32166
- loopStep.inputs,
32167
- (0, import_fp8.cloneDeep)(this._context)
32168
- );
32169
32205
  let tempOutput = { items: loopSteps, iterations: iterationCount };
32170
32206
  try {
32171
- newInput.binding = typecastForLooping(
32207
+ loopStep.inputs.binding = typecastForLooping(
32172
32208
  loopStep,
32173
- newInput
32209
+ loopStep.inputs
32174
32210
  );
32175
32211
  } catch (err) {
32176
32212
  this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
@@ -32183,7 +32219,7 @@ var Orchestrator = class {
32183
32219
  }
32184
32220
  let item = [];
32185
32221
  if (typeof loopStep.inputs.binding === "string" && loopStep.inputs.option === "String") {
32186
- item = stringSplit(newInput.binding);
32222
+ item = stringSplit(loopStep.inputs.binding);
32187
32223
  } else if (Array.isArray(loopStep.inputs.binding)) {
32188
32224
  item = loopStep.inputs.binding;
32189
32225
  }
@@ -32326,7 +32362,21 @@ var Orchestrator = class {
32326
32362
  loopSteps = [];
32327
32363
  }
32328
32364
  }
32329
- await storeLog2(this._automation, this.executionOutput);
32365
+ const end2 = import_perf_hooks2.performance.now();
32366
+ const executionTime = end2 - start2;
32367
+ console.info(`Execution time: ${executionTime} milliseconds`, {
32368
+ _logKey: "automation",
32369
+ executionTime
32370
+ });
32371
+ try {
32372
+ await storeLog2(this._automation, this.executionOutput);
32373
+ } catch (e) {
32374
+ if (e.status === 413 && ((_b = e.request) == null ? void 0 : _b.data)) {
32375
+ delete e.request.data;
32376
+ e.request.data = { message: "removed due to large size" };
32377
+ }
32378
+ logging_exports.logAlert("Error writing automation log", e);
32379
+ }
32330
32380
  if (isProdAppID2(this._appId) && isRecurring(automation) && metadata) {
32331
32381
  await this.updateMetadata(metadata);
32332
32382
  }
@@ -32335,20 +32385,28 @@ var Orchestrator = class {
32335
32385
  };
32336
32386
  function execute3(job, callback) {
32337
32387
  const appId = job.data.event.appId;
32388
+ const automationId = job.data.automation._id;
32338
32389
  if (!appId) {
32339
32390
  throw new Error("Unable to execute, event doesn't contain app ID.");
32340
32391
  }
32341
- return context_exports.doInAppContext(appId, async () => {
32342
- const envVars = await getEnvironmentVariables2();
32343
- await context_exports.doInEnvironmentContext(envVars, async () => {
32344
- const automationOrchestrator = new Orchestrator(job);
32345
- try {
32346
- const response2 = await automationOrchestrator.execute();
32347
- callback(null, response2);
32348
- } catch (err) {
32349
- callback(err);
32350
- }
32351
- });
32392
+ if (!automationId) {
32393
+ throw new Error("Unable to execute, event doesn't contain automation ID.");
32394
+ }
32395
+ return context_exports.doInAutomationContext({
32396
+ appId,
32397
+ automationId,
32398
+ task: async () => {
32399
+ const envVars = await getEnvironmentVariables2();
32400
+ await context_exports.doInEnvironmentContext(envVars, async () => {
32401
+ const automationOrchestrator = new Orchestrator(job);
32402
+ try {
32403
+ const response2 = await automationOrchestrator.execute();
32404
+ callback(null, response2);
32405
+ } catch (err) {
32406
+ callback(err);
32407
+ }
32408
+ });
32409
+ }
32352
32410
  });
32353
32411
  }
32354
32412
  function executeSynchronously(job) {