bullmq 5.47.0 → 5.47.2
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/cjs/classes/flow-producer.js +1 -1
- package/dist/cjs/classes/flow-producer.js.map +1 -1
- package/dist/cjs/classes/scripts.js +1 -1
- package/dist/cjs/classes/scripts.js.map +1 -1
- package/dist/cjs/commands/includes/{moveParentToFailedIfNeeded.lua → moveChildFromDependenciesIfNeeded.lua} +40 -29
- package/dist/cjs/commands/includes/moveParentToWaitIfNeeded.lua +2 -2
- package/dist/cjs/commands/moveStalledJobsToWait-9.lua +2 -31
- package/dist/cjs/commands/moveToFinished-14.lua +3 -23
- package/dist/cjs/commands/moveToWaitingChildren-8.lua +2 -32
- package/dist/cjs/scripts/addDelayedJob-6.js +2 -2
- package/dist/cjs/scripts/addParentJob-4.js +2 -2
- package/dist/cjs/scripts/addPrioritizedJob-8.js +2 -2
- package/dist/cjs/scripts/addStandardJob-8.js +2 -2
- package/dist/cjs/scripts/moveStalledJobsToWait-9.js +42 -60
- package/dist/cjs/scripts/moveStalledJobsToWait-9.js.map +1 -1
- package/dist/cjs/scripts/moveToFinished-14.js +43 -52
- package/dist/cjs/scripts/moveToFinished-14.js.map +1 -1
- package/dist/cjs/scripts/moveToWaitingChildren-8.js +42 -62
- package/dist/cjs/scripts/moveToWaitingChildren-8.js.map +1 -1
- package/dist/cjs/tsconfig-cjs.tsbuildinfo +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/classes/flow-producer.js +1 -1
- package/dist/esm/classes/flow-producer.js.map +1 -1
- package/dist/esm/classes/scripts.js +1 -1
- package/dist/esm/classes/scripts.js.map +1 -1
- package/dist/esm/commands/includes/{moveParentToFailedIfNeeded.lua → moveChildFromDependenciesIfNeeded.lua} +40 -29
- package/dist/esm/commands/includes/moveParentToWaitIfNeeded.lua +2 -2
- package/dist/esm/commands/moveStalledJobsToWait-9.lua +2 -31
- package/dist/esm/commands/moveToFinished-14.lua +3 -23
- package/dist/esm/commands/moveToWaitingChildren-8.lua +2 -32
- package/dist/esm/scripts/addDelayedJob-6.js +2 -2
- package/dist/esm/scripts/addParentJob-4.js +2 -2
- package/dist/esm/scripts/addPrioritizedJob-8.js +2 -2
- package/dist/esm/scripts/addStandardJob-8.js +2 -2
- package/dist/esm/scripts/moveStalledJobsToWait-9.js +42 -60
- package/dist/esm/scripts/moveStalledJobsToWait-9.js.map +1 -1
- package/dist/esm/scripts/moveToFinished-14.js +43 -52
- package/dist/esm/scripts/moveToFinished-14.js.map +1 -1
- package/dist/esm/scripts/moveToWaitingChildren-8.js +42 -62
- package/dist/esm/scripts/moveToWaitingChildren-8.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
@@ -271,8 +271,8 @@ local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
|
|
271
271
|
end
|
272
272
|
end
|
273
273
|
local function moveParentToWaitIfNeeded(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
|
274
|
-
local
|
275
|
-
if
|
274
|
+
local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
|
275
|
+
if doNotHavePendingDependencies then
|
276
276
|
moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
|
277
277
|
end
|
278
278
|
end
|
@@ -458,7 +458,9 @@ local function removeJobsOnFail(queueKeyPrefix, failedKey, jobId, opts, timestam
|
|
458
458
|
end
|
459
459
|
end
|
460
460
|
end
|
461
|
-
local
|
461
|
+
local moveParentToFailedIfNeeded
|
462
|
+
local moveChildFromDependenciesIfNeeded
|
463
|
+
moveParentToFailedIfNeeded = function (parentQueueKey, parentKey, parentId, jobIdKey, timestamp)
|
462
464
|
if rcall("EXISTS", parentKey) == 1 then
|
463
465
|
local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
|
464
466
|
local parentDelayedKey = parentQueueKey .. ":delayed"
|
@@ -486,34 +488,7 @@ local function moveParentToFailedIfNeeded(parentQueueKey, parentKey, parentId, j
|
|
486
488
|
failedReason, "prev", prevState)
|
487
489
|
local jobAttributes = rcall("HMGET", parentKey, "parent", "deid", "opts")
|
488
490
|
removeDeduplicationKeyIfNeeded(parentQueueKey .. ":", jobAttributes[2])
|
489
|
-
|
490
|
-
local parentData = cjson.decode(jobAttributes[1])
|
491
|
-
local grandParentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
492
|
-
local grandParentUnsuccesssful = grandParentKey .. ":unsuccessful"
|
493
|
-
rcall("ZADD", grandParentUnsuccesssful, timestamp, parentKey)
|
494
|
-
if parentData['fpof'] then
|
495
|
-
moveParentToFailedIfNeeded(
|
496
|
-
parentData['queueKey'],
|
497
|
-
parentData['queueKey'] .. ':' .. parentData['id'],
|
498
|
-
parentData['id'],
|
499
|
-
parentKey,
|
500
|
-
timestamp
|
501
|
-
)
|
502
|
-
elseif parentData['cpof'] then
|
503
|
-
moveParentToWait(parentData['queueKey'], parentKey, parentData['id'], timestamp)
|
504
|
-
elseif parentData['idof'] or parentData['rdof'] then
|
505
|
-
local grandParentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
506
|
-
local grandParentDependenciesSet = grandParentKey .. ":dependencies"
|
507
|
-
if rcall("SREM", grandParentDependenciesSet, parentKey) == 1 then
|
508
|
-
moveParentToWaitIfNeeded(parentData['queueKey'], grandParentDependenciesSet,
|
509
|
-
grandParentKey, parentData['id'], timestamp)
|
510
|
-
if parentData['idof'] then
|
511
|
-
local grandParentFailedSet = grandParentKey .. ":failed"
|
512
|
-
rcall("HSET", grandParentFailedSet, parentKey, failedReason)
|
513
|
-
end
|
514
|
-
end
|
515
|
-
end
|
516
|
-
end
|
491
|
+
moveChildFromDependenciesIfNeeded(jobAttributes[1], parentKey, failedReason, timestamp)
|
517
492
|
local parentRawOpts = jobAttributes[3]
|
518
493
|
local parentOpts = cjson.decode(parentRawOpts)
|
519
494
|
removeJobsOnFail(parentQueuePrefix, parentFailedKey, parentId, parentOpts, timestamp)
|
@@ -526,6 +501,41 @@ local function moveParentToFailedIfNeeded(parentQueueKey, parentKey, parentId, j
|
|
526
501
|
end
|
527
502
|
end
|
528
503
|
end
|
504
|
+
moveChildFromDependenciesIfNeeded = function (rawParentData, childKey, failedReason, timestamp)
|
505
|
+
if rawParentData then
|
506
|
+
local parentData = cjson.decode(rawParentData)
|
507
|
+
local parentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
508
|
+
local parentDependenciesChildrenKey = parentKey .. ":dependencies"
|
509
|
+
if parentData['fpof'] then
|
510
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
511
|
+
local parentUnsuccesssfulChildrenKey = parentKey .. ":unsuccessful"
|
512
|
+
rcall("ZADD", parentUnsuccesssfulChildrenKey, timestamp, childKey)
|
513
|
+
moveParentToFailedIfNeeded(
|
514
|
+
parentData['queueKey'],
|
515
|
+
parentKey,
|
516
|
+
parentData['id'],
|
517
|
+
childKey,
|
518
|
+
timestamp
|
519
|
+
)
|
520
|
+
end
|
521
|
+
elseif parentData['cpof'] then
|
522
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
523
|
+
local parentFailedChildrenKey = parentKey .. ":failed"
|
524
|
+
rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
|
525
|
+
moveParentToWait(parentData['queueKey'], parentKey, parentData['id'], timestamp)
|
526
|
+
end
|
527
|
+
elseif parentData['idof'] or parentData['rdof'] then
|
528
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
529
|
+
moveParentToWaitIfNeeded(parentData['queueKey'], parentDependenciesChildrenKey,
|
530
|
+
parentKey, parentData['id'], timestamp)
|
531
|
+
if parentData['idof'] then
|
532
|
+
local parentFailedChildrenKey = parentKey .. ":failed"
|
533
|
+
rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
529
539
|
--[[
|
530
540
|
Function to move job from wait state to active.
|
531
541
|
Input:
|
@@ -682,7 +692,7 @@ if rcall("EXISTS", jobIdKey) == 1 then -- Make sure job exists
|
|
682
692
|
local parentKey = jobAttributes[1] or ""
|
683
693
|
local parentId = ""
|
684
694
|
local parentQueueKey = ""
|
685
|
-
if jobAttributes[2] then
|
695
|
+
if jobAttributes[2] then -- TODO: need to revisit this logic if it's still needed
|
686
696
|
local jsonDecodedParent = cjson.decode(jobAttributes[2])
|
687
697
|
parentId = jsonDecodedParent['id']
|
688
698
|
parentQueueKey = jsonDecodedParent['queueKey']
|
@@ -717,26 +727,7 @@ if rcall("EXISTS", jobIdKey) == 1 then -- Make sure job exists
|
|
717
727
|
timestamp)
|
718
728
|
end
|
719
729
|
else
|
720
|
-
|
721
|
-
local unsuccesssfulSet = parentKey .. ":unsuccessful"
|
722
|
-
rcall("ZADD", unsuccesssfulSet, timestamp, jobIdKey)
|
723
|
-
if opts['fpof'] then
|
724
|
-
moveParentToFailedIfNeeded(parentQueueKey, parentKey, parentId, jobIdKey, timestamp)
|
725
|
-
elseif opts['cpof'] then
|
726
|
-
local failedSet = parentKey .. ":failed"
|
727
|
-
rcall("HSET", failedSet, jobIdKey, ARGV[4])
|
728
|
-
moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
|
729
|
-
end
|
730
|
-
elseif opts['idof'] or opts['rdof'] then
|
731
|
-
local dependenciesSet = parentKey .. ":dependencies"
|
732
|
-
if rcall("SREM", dependenciesSet, jobIdKey) == 1 then
|
733
|
-
moveParentToWaitIfNeeded(parentQueueKey, dependenciesSet, parentKey, parentId, timestamp)
|
734
|
-
if opts['idof'] then
|
735
|
-
local failedSet = parentKey .. ":failed"
|
736
|
-
rcall("HSET", failedSet, jobIdKey, ARGV[4])
|
737
|
-
end
|
738
|
-
end
|
739
|
-
end
|
730
|
+
moveChildFromDependenciesIfNeeded(jobAttributes[2], jobIdKey, ARGV[4], timestamp)
|
740
731
|
end
|
741
732
|
end
|
742
733
|
local attemptsMade = rcall("HINCRBY", jobIdKey, "atm", 1)
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"moveToFinished-14.js","sourceRoot":"","sources":["../../../src/scripts/moveToFinished-14.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
1
|
+
{"version":3,"file":"moveToFinished-14.js","sourceRoot":"","sources":["../../../src/scripts/moveToFinished-14.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8zBf,CAAC;AACF,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,gBAAgB;IACtB,OAAO;IACP,IAAI,EAAE,EAAE;CACT,CAAC"}
|
@@ -172,8 +172,8 @@ local function moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
|
|
172
172
|
end
|
173
173
|
end
|
174
174
|
local function moveParentToWaitIfNeeded(parentQueueKey, parentDependenciesKey, parentKey, parentId, timestamp)
|
175
|
-
local
|
176
|
-
if
|
175
|
+
local doNotHavePendingDependencies = rcall("SCARD", parentDependenciesKey) == 0
|
176
|
+
if doNotHavePendingDependencies then
|
177
177
|
moveParentToWait(parentQueueKey, parentKey, parentId, timestamp)
|
178
178
|
end
|
179
179
|
end
|
@@ -359,7 +359,9 @@ local function removeJobsOnFail(queueKeyPrefix, failedKey, jobId, opts, timestam
|
|
359
359
|
end
|
360
360
|
end
|
361
361
|
end
|
362
|
-
local
|
362
|
+
local moveParentToFailedIfNeeded
|
363
|
+
local moveChildFromDependenciesIfNeeded
|
364
|
+
moveParentToFailedIfNeeded = function (parentQueueKey, parentKey, parentId, jobIdKey, timestamp)
|
363
365
|
if rcall("EXISTS", parentKey) == 1 then
|
364
366
|
local parentWaitingChildrenKey = parentQueueKey .. ":waiting-children"
|
365
367
|
local parentDelayedKey = parentQueueKey .. ":delayed"
|
@@ -387,34 +389,7 @@ local function moveParentToFailedIfNeeded(parentQueueKey, parentKey, parentId, j
|
|
387
389
|
failedReason, "prev", prevState)
|
388
390
|
local jobAttributes = rcall("HMGET", parentKey, "parent", "deid", "opts")
|
389
391
|
removeDeduplicationKeyIfNeeded(parentQueueKey .. ":", jobAttributes[2])
|
390
|
-
|
391
|
-
local parentData = cjson.decode(jobAttributes[1])
|
392
|
-
local grandParentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
393
|
-
local grandParentUnsuccesssful = grandParentKey .. ":unsuccessful"
|
394
|
-
rcall("ZADD", grandParentUnsuccesssful, timestamp, parentKey)
|
395
|
-
if parentData['fpof'] then
|
396
|
-
moveParentToFailedIfNeeded(
|
397
|
-
parentData['queueKey'],
|
398
|
-
parentData['queueKey'] .. ':' .. parentData['id'],
|
399
|
-
parentData['id'],
|
400
|
-
parentKey,
|
401
|
-
timestamp
|
402
|
-
)
|
403
|
-
elseif parentData['cpof'] then
|
404
|
-
moveParentToWait(parentData['queueKey'], parentKey, parentData['id'], timestamp)
|
405
|
-
elseif parentData['idof'] or parentData['rdof'] then
|
406
|
-
local grandParentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
407
|
-
local grandParentDependenciesSet = grandParentKey .. ":dependencies"
|
408
|
-
if rcall("SREM", grandParentDependenciesSet, parentKey) == 1 then
|
409
|
-
moveParentToWaitIfNeeded(parentData['queueKey'], grandParentDependenciesSet,
|
410
|
-
grandParentKey, parentData['id'], timestamp)
|
411
|
-
if parentData['idof'] then
|
412
|
-
local grandParentFailedSet = grandParentKey .. ":failed"
|
413
|
-
rcall("HSET", grandParentFailedSet, parentKey, failedReason)
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
417
|
-
end
|
392
|
+
moveChildFromDependenciesIfNeeded(jobAttributes[1], parentKey, failedReason, timestamp)
|
418
393
|
local parentRawOpts = jobAttributes[3]
|
419
394
|
local parentOpts = cjson.decode(parentRawOpts)
|
420
395
|
removeJobsOnFail(parentQueuePrefix, parentFailedKey, parentId, parentOpts, timestamp)
|
@@ -427,6 +402,41 @@ local function moveParentToFailedIfNeeded(parentQueueKey, parentKey, parentId, j
|
|
427
402
|
end
|
428
403
|
end
|
429
404
|
end
|
405
|
+
moveChildFromDependenciesIfNeeded = function (rawParentData, childKey, failedReason, timestamp)
|
406
|
+
if rawParentData then
|
407
|
+
local parentData = cjson.decode(rawParentData)
|
408
|
+
local parentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
409
|
+
local parentDependenciesChildrenKey = parentKey .. ":dependencies"
|
410
|
+
if parentData['fpof'] then
|
411
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
412
|
+
local parentUnsuccesssfulChildrenKey = parentKey .. ":unsuccessful"
|
413
|
+
rcall("ZADD", parentUnsuccesssfulChildrenKey, timestamp, childKey)
|
414
|
+
moveParentToFailedIfNeeded(
|
415
|
+
parentData['queueKey'],
|
416
|
+
parentKey,
|
417
|
+
parentData['id'],
|
418
|
+
childKey,
|
419
|
+
timestamp
|
420
|
+
)
|
421
|
+
end
|
422
|
+
elseif parentData['cpof'] then
|
423
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
424
|
+
local parentFailedChildrenKey = parentKey .. ":failed"
|
425
|
+
rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
|
426
|
+
moveParentToWait(parentData['queueKey'], parentKey, parentData['id'], timestamp)
|
427
|
+
end
|
428
|
+
elseif parentData['idof'] or parentData['rdof'] then
|
429
|
+
if rcall("SREM", parentDependenciesChildrenKey, childKey) == 1 then
|
430
|
+
moveParentToWaitIfNeeded(parentData['queueKey'], parentDependenciesChildrenKey,
|
431
|
+
parentKey, parentData['id'], timestamp)
|
432
|
+
if parentData['idof'] then
|
433
|
+
local parentFailedChildrenKey = parentKey .. ":failed"
|
434
|
+
rcall("HSET", parentFailedChildrenKey, childKey, failedReason)
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
430
440
|
local function removeLock(jobKey, stalledKey, token, jobId)
|
431
441
|
if token ~= "0" then
|
432
442
|
local lockKey = jobKey .. ':lock'
|
@@ -469,37 +479,7 @@ if rcall("EXISTS", jobKey) == 1 then
|
|
469
479
|
local rawParentData = jobAttributes[1]
|
470
480
|
local rawOpts = jobAttributes[3]
|
471
481
|
local opts = cjson.decode(rawOpts)
|
472
|
-
|
473
|
-
if opts['fpof'] or opts['cpof'] then
|
474
|
-
local parentData = cjson.decode(rawParentData)
|
475
|
-
local parentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
476
|
-
local parentUnsuccesssful = parentKey .. ":unsuccessful"
|
477
|
-
rcall("ZADD", parentUnsuccesssful, timestamp, jobKey)
|
478
|
-
if opts['fpof'] then
|
479
|
-
moveParentToFailedIfNeeded(
|
480
|
-
parentData['queueKey'],
|
481
|
-
parentData['queueKey'] .. ':' .. parentData['id'],
|
482
|
-
parentData['id'],
|
483
|
-
jobKey,
|
484
|
-
timestamp
|
485
|
-
)
|
486
|
-
elseif opts['cpof'] then
|
487
|
-
moveParentToWait(parentData['queueKey'], parentKey, parentData['id'], timestamp)
|
488
|
-
end
|
489
|
-
elseif opts['idof'] or opts['rdof'] then
|
490
|
-
local parentData = cjson.decode(rawParentData)
|
491
|
-
local parentKey = parentData['queueKey'] .. ':' .. parentData['id']
|
492
|
-
local dependenciesSet = parentKey .. ":dependencies"
|
493
|
-
if rcall("SREM", dependenciesSet, jobKey) == 1 then
|
494
|
-
moveParentToWaitIfNeeded(parentData['queueKey'], dependenciesSet,
|
495
|
-
parentKey, parentData['id'], timestamp)
|
496
|
-
if opts['idof'] then
|
497
|
-
local failedSet = parentKey .. ":failed"
|
498
|
-
rcall("HSET", failedSet, jobKey, failedReason)
|
499
|
-
end
|
500
|
-
end
|
501
|
-
end
|
502
|
-
end
|
482
|
+
moveChildFromDependenciesIfNeeded(rawParentData, jobKey, failedReason, timestamp)
|
503
483
|
removeJobsOnFail(ARGV[5], failedKey, jobId, opts, timestamp)
|
504
484
|
return 0
|
505
485
|
else
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"moveToWaitingChildren-8.js","sourceRoot":"","sources":["../../../src/scripts/moveToWaitingChildren-8.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG
|
1
|
+
{"version":3,"file":"moveToWaitingChildren-8.js","sourceRoot":"","sources":["../../../src/scripts/moveToWaitingChildren-8.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ff,CAAC;AACF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,uBAAuB;IAC7B,OAAO;IACP,IAAI,EAAE,CAAC;CACR,CAAC"}
|