@effect-app/infra 1.23.4 → 1.24.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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @effect-app/infra
2
2
 
3
+ ## 1.24.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bs
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @effect-app/infra-adapters@1.12.0
13
+
14
+ ## 1.23.5
15
+
16
+ ### Patch Changes
17
+
18
+ - 6ffe991: add optimistic concurrency
19
+
3
20
  ## 1.23.4
4
21
 
5
22
  ### Patch Changes
@@ -5,12 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.QueueId = void 0;
7
7
  exports.makeSQLQueue = makeSQLQueue;
8
+ var _SQL = require("@effect-app/infra-adapters/SQL");
8
9
  var _setupRequest = require("@effect-app/infra/api/setupRequest");
9
10
  var _RequestContext = require("@effect-app/infra/RequestContext");
10
11
  var _errors = require("@effect-app/infra/services/QueueMaker/errors");
11
12
  var _service = require("@effect-app/infra/services/QueueMaker/service");
12
13
  var _RequestContextContainer = require("@effect-app/infra/services/RequestContextContainer");
13
14
  var _sql = require("@effect/sql");
15
+ var _crypto = require("crypto");
14
16
  var _dateFns = require("date-fns");
15
17
  var _effectApp = require("effect-app");
16
18
  var _ids = require("effect-app/ids");
@@ -18,41 +20,42 @@ var _schema = require("effect-app/schema");
18
20
  var _utils = require("effect-app/utils");
19
21
  var _logger = require("../../logger.cjs");
20
22
  const QueueId = exports.QueueId = _effectApp.S.Number.pipe(_effectApp.S.brand("QueueId"));
21
- /**
22
- * Currently limited to one process draining at a time, due to in-process Semaphore instead of row-level locking.
23
- */
23
+ // TODO: let the model track and Auto Generate versionColumn on every update instead
24
24
  function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
25
25
  return _effectApp.Effect.gen(function* () {
26
26
  const base = {
27
- id: _sql.Model.Generated(QueueId),
28
- meta: _sql.Model.JsonFromString(_service.QueueMeta),
27
+ id: _SQL.Model.Generated(QueueId),
28
+ meta: _SQL.Model.JsonFromString(_service.QueueMeta),
29
29
  name: _effectApp.S.NonEmptyString255,
30
- createdAt: _sql.Model.DateTimeInsert,
31
- updatedAt: _sql.Model.DateTimeUpdate,
30
+ createdAt: _SQL.Model.DateTimeInsert,
31
+ updatedAt: _SQL.Model.DateTimeUpdate,
32
32
  // TODO: at+owner
33
- processingAt: _sql.Model.FieldOption(_effectApp.S.Date),
34
- finishedAt: _sql.Model.FieldOption(_effectApp.S.Date)
33
+ processingAt: _SQL.Model.FieldOption(_effectApp.S.Date),
34
+ finishedAt: _SQL.Model.FieldOption(_effectApp.S.Date),
35
+ etag: _effectApp.S.String // TODO: use a Model thing that auto updates it?
35
36
  // TODO: record locking.. / optimistic locking
36
37
  // rowVersion: Model.DateTimeFromNumberWithNow
37
38
  };
38
- class Queue extends _sql.Model.Class("Queue")({
39
- body: _sql.Model.JsonFromString(schema),
39
+ class Queue extends _SQL.Model.Class("Queue")({
40
+ body: _SQL.Model.JsonFromString(schema),
40
41
  ...base
41
42
  }) {}
42
- class Drain extends _sql.Model.Class("Drain")({
43
- body: _sql.Model.JsonFromString(drainSchema),
43
+ class Drain extends _SQL.Model.Class("Drain")({
44
+ body: _SQL.Model.JsonFromString(drainSchema),
44
45
  ...base
45
46
  }) {}
46
47
  const sql = yield* _sql.SqlClient.SqlClient;
47
- const queueRepo = yield* _sql.Model.makeRepository(Queue, {
48
+ const queueRepo = yield* _SQL.Model.makeRepository(Queue, {
48
49
  tableName: "queue",
49
50
  spanPrefix: "QueueRepo",
50
- idColumn: "id"
51
+ idColumn: "id",
52
+ versionColumn: "etag"
51
53
  });
52
- const drainRepo = yield* _sql.Model.makeRepository(Drain, {
54
+ const drainRepo = yield* _SQL.Model.makeRepository(Drain, {
53
55
  tableName: "queue",
54
56
  spanPrefix: "DrainRepo",
55
- idColumn: "id"
57
+ idColumn: "id",
58
+ versionColumn: "etag"
56
59
  });
57
60
  const decodeDrain = _effectApp.S.decode(Drain);
58
61
  const drain = () => {
@@ -62,8 +65,6 @@ function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
62
65
  WHERE name = ${queueDrainName} AND finishedAt IS NULL AND (processingAt IS NULL OR processingAt < ${limit.getTime()})
63
66
  LIMIT 1`;
64
67
  };
65
- // temporary workaround until we have a SQLite rowversion..
66
- const lock = yield* _effectApp.Effect.makeSemaphore(1);
67
68
  const q = {
68
69
  offer: (body, meta) => _effectApp.Effect.gen(function* () {
69
70
  yield* queueRepo.insert(Queue.insert.make({
@@ -71,28 +72,27 @@ function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
71
72
  meta,
72
73
  name: queueName,
73
74
  processingAt: _effectApp.Option.none(),
74
- finishedAt: _effectApp.Option.none()
75
+ finishedAt: _effectApp.Option.none(),
76
+ etag: (0, _crypto.randomUUID)()
75
77
  }));
76
78
  }),
77
79
  take: _effectApp.Effect.gen(function* () {
78
80
  while (true) {
79
- const first = yield* lock.withPermits(1)(_effectApp.Effect.gen(function* () {
80
- const [first] = yield* drain();
81
- if (first) {
82
- const dec = yield* decodeDrain(first);
83
- const {
84
- createdAt,
85
- updatedAt,
86
- ...rest
87
- } = dec;
88
- yield* drainRepo.update(Drain.update.make({
89
- ...rest,
90
- processingAt: _effectApp.Option.some(new Date())
91
- }));
92
- return dec;
93
- }
94
- return null;
95
- }));
81
+ const [first] = yield* drain();
82
+ if (first) {
83
+ const dec = yield* decodeDrain(first);
84
+ const {
85
+ createdAt,
86
+ updatedAt,
87
+ ...rest
88
+ } = dec;
89
+ yield* drainRepo.update(Drain.update.make({
90
+ ...rest,
91
+ processingAt: _effectApp.Option.some(new Date())
92
+ }) // auto in lib , etag: randomUUID()
93
+ );
94
+ return dec;
95
+ }
96
96
  if (first) return first;
97
97
  yield* _effectApp.Effect.sleep(250);
98
98
  }
@@ -104,7 +104,7 @@ function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
104
104
  }) => drainRepo.update(Drain.update.make({
105
105
  ...q,
106
106
  finishedAt: _effectApp.Option.some(new Date())
107
- }))
107
+ })) // auto in lib , etag: randomUUID()
108
108
  };
109
109
  const rcc = yield* _RequestContextContainer.RequestContextContainer;
110
110
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"SQLQueue.cjs","names":["_setupRequest","require","_RequestContext","_errors","_service","_RequestContextContainer","_sql","_dateFns","_effectApp","_ids","_schema","_utils","_logger","QueueId","exports","S","Number","pipe","brand","makeSQLQueue","queueName","queueDrainName","schema","drainSchema","Effect","gen","base","id","Model","Generated","meta","JsonFromString","QueueMeta","name","NonEmptyString255","createdAt","DateTimeInsert","updatedAt","DateTimeUpdate","processingAt","FieldOption","Date","finishedAt","Queue","Class","body","Drain","sql","SqlClient","queueRepo","makeRepository","tableName","spanPrefix","idColumn","drainRepo","decodeDrain","decode","drain","limit","subMinutes","getTime","lock","makeSemaphore","q","offer","insert","make","Option","none","take","first","withPermits","dec","rest","update","some","sleep","finish","rcc","RequestContextContainer","publish","messages","requestContext","span","serviceOption","Tracer","ParentSpan","forEach","m","RequestContext","getOrUndefined","discard","withSpan","captureStackTrace","kind","attributes","map","_","_tag","handleEvent","sessionId","silenceAndReportError","reportNonInterruptedFailure","processMessage","msg","succeed","flatMap","effect","InfraLogger","logInfo","annotateLogs","pretty","zipRight","setupRequestContext","inherit","RequestId","locale","withParentSpan","externalSpan","x","uninterruptible","fork","Fiber","join","tap","forever"],"sources":["../../../src/services/QueueMaker/SQLQueue.ts"],"sourcesContent":[null],"mappings":";;;;;;;AAAA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,eAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAEA,IAAAG,QAAA,GAAAH,OAAA;AACA,IAAAI,wBAAA,GAAAJ,OAAA;AACA,IAAAK,IAAA,GAAAL,OAAA;AACA,IAAAM,QAAA,GAAAN,OAAA;AACA,IAAAO,UAAA,GAAAP,OAAA;AACA,IAAAQ,IAAA,GAAAR,OAAA;AACA,IAAAS,OAAA,GAAAT,OAAA;AACA,IAAAU,MAAA,GAAAV,OAAA;AACA,IAAAW,OAAA,GAAAX,OAAA;AAEO,MAAMY,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAGE,YAAC,CAACC,MAAM,CAACC,IAAI,CAACF,YAAC,CAACG,KAAK,CAAC,SAAS,CAAC,CAAC;AAGxD;;;AAGM,SAAUC,YAAYA,CAM1BC,SAA4B,EAC5BC,cAAiC,EACjCC,MAA2B,EAC3BC,WAA0C;EAE1C,OAAOC,iBAAM,CAACC,GAAG,CAAC,aAAS;IACzB,MAAMC,IAAI,GAAG;MACXC,EAAE,EAAEC,UAAK,CAACC,SAAS,CAAChB,OAAO,CAAC;MAC5BiB,IAAI,EAAEF,UAAK,CAACG,cAAc,CAACC,kBAAS,CAAC;MACrCC,IAAI,EAAElB,YAAC,CAACmB,iBAAiB;MACzBC,SAAS,EAAEP,UAAK,CAACQ,cAAc;MAC/BC,SAAS,EAAET,UAAK,CAACU,cAAc;MAC/B;MACAC,YAAY,EAAEX,UAAK,CAACY,WAAW,CAACzB,YAAC,CAAC0B,IAAI,CAAC;MACvCC,UAAU,EAAEd,UAAK,CAACY,WAAW,CAACzB,YAAC,CAAC0B,IAAI;MACpC;MACA;KACD;IACD,MAAME,KAAM,SAAQf,UAAK,CAACgB,KAAK,CAAQ,OAAO,CAAC,CAAC;MAC9CC,IAAI,EAAEjB,UAAK,CAACG,cAAc,CAACT,MAAM,CAAC;MAClC,GAAGI;KACJ,CAAC;IACF,MAAMoB,KAAM,SAAQlB,UAAK,CAACgB,KAAK,CAAQ,OAAO,CAAC,CAAC;MAC9CC,IAAI,EAAEjB,UAAK,CAACG,cAAc,CAACR,WAAW,CAAC;MACvC,GAAGG;KACJ,CAAC;IACF,MAAMqB,GAAG,GAAG,OAAOC,cAAS,CAACA,SAAS;IAEtC,MAAMC,SAAS,GAAG,OAAOrB,UAAK,CAACsB,cAAc,CAACP,KAAK,EAAE;MACnDQ,SAAS,EAAE,OAAO;MAClBC,UAAU,EAAE,WAAW;MACvBC,QAAQ,EAAE;KACX,CAAC;IAEF,MAAMC,SAAS,GAAG,OAAO1B,UAAK,CAACsB,cAAc,CAACJ,KAAK,EAAE;MACnDK,SAAS,EAAE,OAAO;MAClBC,UAAU,EAAE,WAAW;MACvBC,QAAQ,EAAE;KACX,CAAC;IAEF,MAAME,WAAW,GAAGxC,YAAC,CAACyC,MAAM,CAACV,KAAK,CAAC;IAEnC,MAAMW,KAAK,GAAGA,CAAA,KAAK;MACjB,MAAMC,KAAK,GAAG,IAAAC,mBAAU,EAAC,IAAIlB,IAAI,EAAE,EAAE,EAAE,CAAC;MACxC,OAAOM,GAAyB;;mBAEnB1B,cAAc,uEAAuEqC,KAAK,CAACE,OAAO,EAAE;YAC3G;IACR,CAAC;IAED;IACA,MAAMC,IAAI,GAAG,OAAOrC,iBAAM,CAACsC,aAAa,CAAC,CAAC,CAAC;IAE3C,MAAMC,CAAC,GAAG;MACRC,KAAK,EAAEA,CAACnB,IAAS,EAAEf,IAA2B,KAC5CN,iBAAM,CAACC,GAAG,CAAC,aAAS;QAClB,OAAOwB,SAAS,CAACgB,MAAM,CACrBtB,KAAK,CAACsB,MAAM,CAACC,IAAI,CAAC;UAChBrB,IAAI;UACJf,IAAI;UACJG,IAAI,EAAEb,SAAS;UACfmB,YAAY,EAAE4B,iBAAM,CAACC,IAAI,EAAE;UAC3B1B,UAAU,EAAEyB,iBAAM,CAACC,IAAI;SACxB,CAAC,CACH;MACH,CAAC,CAAC;MACJC,IAAI,EAAE7C,iBAAM,CAACC,GAAG,CAAC,aAAS;QACxB,OAAO,IAAI,EAAE;UACX,MAAM6C,KAAK,GAAG,OAAOT,IAAI,CAACU,WAAW,CAAC,CAAC,CAAC,CAAC/C,iBAAM,CAACC,GAAG,CAAC,aAAS;YAC3D,MAAM,CAAC6C,KAAK,CAAC,GAAG,OAAOb,KAAK,EAAE;YAC9B,IAAIa,KAAK,EAAE;cACT,MAAME,GAAG,GAAG,OAAOjB,WAAW,CAACe,KAAK,CAAC;cACrC,MAAM;gBAAEnC,SAAS;gBAAEE,SAAS;gBAAE,GAAGoC;cAAI,CAAE,GAAGD,GAAG;cAC7C,OAAOlB,SAAS,CAACoB,MAAM,CAAC5B,KAAK,CAAC4B,MAAM,CAACR,IAAI,CAAC;gBAAE,GAAGO,IAAI;gBAAElC,YAAY,EAAE4B,iBAAM,CAACQ,IAAI,CAAC,IAAIlC,IAAI,EAAE;cAAC,CAAE,CAAC,CAAC;cAC9F,OAAO+B,GAAG;YACZ;YACA,OAAO,IAAI;UACb,CAAC,CAAC,CAAC;UACH,IAAIF,KAAK,EAAE,OAAOA,KAAK;UACvB,OAAO9C,iBAAM,CAACoD,KAAK,CAAC,GAAG,CAAC;QAC1B;MACF,CAAC,CAAC;MACFC,MAAM,EAAEA,CAAC;QAAE1C,SAAS;QAAEE,SAAS;QAAE,GAAG0B;MAAC,CAAS,KAC5CT,SAAS,CAACoB,MAAM,CAAC5B,KAAK,CAAC4B,MAAM,CAACR,IAAI,CAAC;QAAE,GAAGH,CAAC;QAAErB,UAAU,EAAEyB,iBAAM,CAACQ,IAAI,CAAC,IAAIlC,IAAI,EAAE;MAAC,CAAE,CAAC;KACpF;IACD,MAAMqC,GAAG,GAAG,OAAOC,gDAAuB;IAE1C,OAAO;MACLC,OAAO,EAAEA,CAAC,GAAGC,QAAQ,KACnBzD,iBAAM,CACHC,GAAG,CAAC,aAAS;QACZ,MAAMyD,cAAc,GAAG,OAAOJ,GAAG,CAACI,cAAc;QAChD,MAAMC,IAAI,GAAG,OAAO3D,iBAAM,CAAC4D,aAAa,CAACC,iBAAM,CAACC,UAAU,CAAC;QAC3D,OAAO,OAAO9D,iBAAM,CACjB+D,OAAO,CACNN,QAAQ,EACPO,CAAC,IACAzB,CAAC,CAACC,KAAK,CAACwB,CAAC,EAAE;UACTN,cAAc,EAAE,IAAIO,8BAAc,CAACP,cAAc,CAAC;UAAE;UACpDC,IAAI,EAAEhB,iBAAM,CAACuB,cAAc,CAACP,IAAI;SACjC,CAAC,EACJ;UACEQ,OAAO,EAAE;SACV,CACF;MACL,CAAC,CAAC,CACD1E,IAAI,CACHO,iBAAM,CAACoE,QAAQ,CAAC,iBAAiB,GAAGxE,SAAS,EAAE;QAC7CyE,iBAAiB,EAAE,KAAK;QACxBC,IAAI,EAAE,UAAU;QAChBC,UAAU,EAAE;UAAE,cAAc,EAAEd,QAAQ,CAACe,GAAG,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI;QAAC;OAC1D,CAAC,CACH;MACLzC,KAAK,EAAEA,CACL0C,WAA2D,EAC3DC,SAAkB,KAElB5E,iBAAM,CAACC,GAAG,CAAC,aAAS;QAClB,MAAM4E,qBAAqB,GAAG,IAAAC,mCAA2B,EAAC;UAAErE,IAAI,EAAE,iBAAiB,GAAGZ;QAAc,CAAE,CAAC;QACvG,MAAMkF,cAAc,GAAIC,GAAU,IAChChF,iBAAM,CACHiF,OAAO,CAACD,GAAG,CAAC,CACZvF,IAAI,CAACO,iBAAM,CACTkF,OAAO,CAAC,CAAC;UAAE7D,IAAI;UAAEf;QAAI,CAAE,KAAI;UAC1B,IAAI6E,MAAM,GAAGC,mBAAW,CACrBC,OAAO,CAAC,IAAIxF,cAAc,+BAA+B,CAAC,CAC1DJ,IAAI,CACHO,iBAAM,CAACsF,YAAY,CAAC;YAAEjE,IAAI,EAAE,IAAAkE,aAAM,EAAClE,IAAI,CAAC;YAAEf,IAAI,EAAE,IAAAiF,aAAM,EAACjF,IAAI;UAAC,CAAE,CAAC,EAC/DN,iBAAM,CAACwF,QAAQ,CAACb,WAAW,CAACtD,IAAI,CAAC,CAAC,EAClCwD,qBAAqB,EACpBJ,CAAC,IACA,IAAAgB,iCAAmB,EACjBhB,CAAC,EACDR,8BAAc,CAACyB,OAAO,CAACpF,IAAI,CAACoD,cAAc,EAAE;YAC1CvD,EAAE,EAAE,IAAAwF,cAAS,EAACtE,IAAI,CAAClB,EAAE,CAAC;YACtByF,MAAM,EAAE,IAAa;YACrBnF,IAAI,EAAE,IAAAC,yBAAiB,EAAC,GAAGb,cAAc,IAAIwB,IAAI,CAACqD,IAAI,EAAE;WACzD,CAAC,CACH,EACH1E,iBAAM,CACHoE,QAAQ,CAAC,gBAAgBvE,cAAc,IAAIwB,IAAI,CAACqD,IAAI,EAAE,EAAE;YACvDL,iBAAiB,EAAE,KAAK;YACxBC,IAAI,EAAE,UAAU;YAChBC,UAAU,EAAE;cACV,YAAY,EAAE1E,cAAc;cAC5B,iBAAiB,EAAE+E,SAAS;cAC5B,aAAa,EAAEvD;;WAElB,CAAC,CACL;UACH,IAAIf,IAAI,CAACqD,IAAI,EAAE;YACbwB,MAAM,GAAGnF,iBAAM,CAAC6F,cAAc,CAACV,MAAM,EAAEtB,iBAAM,CAACiC,YAAY,CAACxF,IAAI,CAACqD,IAAI,CAAC,CAAC;UACxE;UACA,OAAOwB,MAAM;QACf,CAAC,CAAC,CAAC;QAET,OAAO,OAAO5C,CAAC,CACZM,IAAI,CACJpD,IAAI,CACHO,iBAAM,CAACkF,OAAO,CAAEa,CAAC,IACfhB,cAAc,CAACgB,CAAC,CAAC,CAACtG,IAAI,CACpBO,iBAAM,CAACgG,eAAe,EACtBhG,iBAAM,CAACiG,IAAI,EACXjG,iBAAM,CAACkF,OAAO,CAACgB,gBAAK,CAACC,IAAI,CAAC,EAC1BnG,iBAAM,CAACoG,GAAG,CAAC7D,CAAC,CAACc,MAAM,CAAC0C,CAAC,CAAC,CAAC,CACxB,CACF,EACDlB,qBAAqB,EACrB7E,iBAAM,CAACqG,OAAO,CACf;MACL,CAAC;KAC+B;EACtC,CAAC,CAAC;AACJ","ignoreList":[]}
1
+ {"version":3,"file":"SQLQueue.cjs","names":["_SQL","require","_setupRequest","_RequestContext","_errors","_service","_RequestContextContainer","_sql","_crypto","_dateFns","_effectApp","_ids","_schema","_utils","_logger","QueueId","exports","S","Number","pipe","brand","makeSQLQueue","queueName","queueDrainName","schema","drainSchema","Effect","gen","base","id","Model","Generated","meta","JsonFromString","QueueMeta","name","NonEmptyString255","createdAt","DateTimeInsert","updatedAt","DateTimeUpdate","processingAt","FieldOption","Date","finishedAt","etag","String","Queue","Class","body","Drain","sql","SqlClient","queueRepo","makeRepository","tableName","spanPrefix","idColumn","versionColumn","drainRepo","decodeDrain","decode","drain","limit","subMinutes","getTime","q","offer","insert","make","Option","none","randomUUID","take","first","dec","rest","update","some","sleep","finish","rcc","RequestContextContainer","publish","messages","requestContext","span","serviceOption","Tracer","ParentSpan","forEach","m","RequestContext","getOrUndefined","discard","withSpan","captureStackTrace","kind","attributes","map","_","_tag","handleEvent","sessionId","silenceAndReportError","reportNonInterruptedFailure","processMessage","msg","succeed","flatMap","effect","InfraLogger","logInfo","annotateLogs","pretty","zipRight","setupRequestContext","inherit","RequestId","locale","withParentSpan","externalSpan","x","uninterruptible","fork","Fiber","join","tap","forever"],"sources":["../../../src/services/QueueMaker/SQLQueue.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -6,9 +6,6 @@ export declare const QueueId: S.brand<typeof import("@effect/schema/Schema").Num
6
6
  withDefault: S.PropertySignature<":", number, never, ":", number, true, never>;
7
7
  }, "QueueId">;
8
8
  export type QueueId = typeof QueueId.Type;
9
- /**
10
- * Currently limited to one process draining at a time, due to in-process Semaphore instead of row-level locking.
11
- */
12
9
  export declare function makeSQLQueue<Evt extends {
13
10
  id: S.StringId;
14
11
  _tag: string;
@@ -1 +1 @@
1
- {"version":3,"file":"SQLQueue.d.ts","sourceRoot":"","sources":["../../../src/services/QueueMaker/SQLQueue.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oDAAoD,CAAA;AAC5F,OAAO,EAAS,SAAS,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EAAE,MAAM,EAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAIrD,eAAO,MAAM,OAAO;;aAAoC,CAAA;AACxD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,SAAS;IAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC5C,QAAQ,SAAS;IAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACjD,IAAI,EACJ,SAAS,EAET,SAAS,EAAE,iBAAiB,EAC5B,cAAc,EAAE,iBAAiB,EACjC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,EAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC;;YA8G9B,MAAM,EAAE,MAAM,eACP,CAAC,EAAE,EAAE,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,cAC/C,MAAM;yDA0DzB"}
1
+ {"version":3,"file":"SQLQueue.d.ts","sourceRoot":"","sources":["../../../src/services/QueueMaker/SQLQueue.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,uBAAuB,EAAE,MAAM,oDAAoD,CAAA;AAC5F,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,OAAO,EAAE,MAAM,EAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAE7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAIrD,eAAO,MAAM,OAAO;;aAAoC,CAAA;AACxD,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAGzC,wBAAgB,YAAY,CAC1B,GAAG,SAAS;IAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAC5C,QAAQ,SAAS;IAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EACjD,IAAI,EACJ,SAAS,EAET,SAAS,EAAE,iBAAiB,EAC5B,cAAc,EAAE,iBAAiB,EACjC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,EAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC;;YA8G9B,MAAM,EAAE,MAAM,eACP,CAAC,EAAE,EAAE,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,cAC/C,MAAM;yDA0DzB"}
@@ -1,9 +1,11 @@
1
+ import { Model } from "@effect-app/infra-adapters/SQL";
1
2
  import { setupRequestContext } from "@effect-app/infra/api/setupRequest";
2
3
  import { RequestContext } from "@effect-app/infra/RequestContext";
3
4
  import { reportNonInterruptedFailure } from "@effect-app/infra/services/QueueMaker/errors";
4
5
  import { QueueMeta } from "@effect-app/infra/services/QueueMaker/service";
5
6
  import { RequestContextContainer } from "@effect-app/infra/services/RequestContextContainer";
6
- import { Model, SqlClient } from "@effect/sql";
7
+ import { SqlClient } from "@effect/sql";
8
+ import { randomUUID } from "crypto";
7
9
  import { subMinutes } from "date-fns";
8
10
  import { Effect, Fiber, Option, S, Tracer } from "effect-app";
9
11
  import { RequestId } from "effect-app/ids";
@@ -11,9 +13,7 @@ import { NonEmptyString255 } from "effect-app/schema";
11
13
  import { pretty } from "effect-app/utils";
12
14
  import { InfraLogger } from "../../logger.js";
13
15
  export const QueueId = S.Number.pipe(S.brand("QueueId"));
14
- /**
15
- * Currently limited to one process draining at a time, due to in-process Semaphore instead of row-level locking.
16
- */
16
+ // TODO: let the model track and Auto Generate versionColumn on every update instead
17
17
  export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
18
18
  return Effect.gen(function* () {
19
19
  const base = {
@@ -24,7 +24,8 @@ export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
24
24
  updatedAt: Model.DateTimeUpdate,
25
25
  // TODO: at+owner
26
26
  processingAt: Model.FieldOption(S.Date),
27
- finishedAt: Model.FieldOption(S.Date)
27
+ finishedAt: Model.FieldOption(S.Date),
28
+ etag: S.String // TODO: use a Model thing that auto updates it?
28
29
  // TODO: record locking.. / optimistic locking
29
30
  // rowVersion: Model.DateTimeFromNumberWithNow
30
31
  };
@@ -42,12 +43,14 @@ export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
42
43
  const queueRepo = yield* Model.makeRepository(Queue, {
43
44
  tableName: "queue",
44
45
  spanPrefix: "QueueRepo",
45
- idColumn: "id"
46
+ idColumn: "id",
47
+ versionColumn: "etag"
46
48
  });
47
49
  const drainRepo = yield* Model.makeRepository(Drain, {
48
50
  tableName: "queue",
49
51
  spanPrefix: "DrainRepo",
50
- idColumn: "id"
52
+ idColumn: "id",
53
+ versionColumn: "etag"
51
54
  });
52
55
  const decodeDrain = S.decode(Drain);
53
56
  const drain = () => {
@@ -57,8 +60,6 @@ export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
57
60
  WHERE name = ${queueDrainName} AND finishedAt IS NULL AND (processingAt IS NULL OR processingAt < ${limit.getTime()})
58
61
  LIMIT 1`;
59
62
  };
60
- // temporary workaround until we have a SQLite rowversion..
61
- const lock = yield* Effect.makeSemaphore(1);
62
63
  const q = {
63
64
  offer: (body, meta) => Effect.gen(function* () {
64
65
  yield* queueRepo.insert(Queue.insert.make({
@@ -66,27 +67,26 @@ export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
66
67
  meta,
67
68
  name: queueName,
68
69
  processingAt: Option.none(),
69
- finishedAt: Option.none()
70
+ finishedAt: Option.none(),
71
+ etag: randomUUID()
70
72
  }));
71
73
  }),
72
74
  take: Effect.gen(function* () {
73
75
  while (true) {
74
- const first = yield* lock.withPermits(1)(Effect.gen(function* () {
75
- const [first] = yield* drain();
76
- if (first) {
77
- const dec = yield* decodeDrain(first);
78
- const { createdAt, updatedAt, ...rest } = dec;
79
- yield* drainRepo.update(Drain.update.make({ ...rest, processingAt: Option.some(new Date()) }));
80
- return dec;
81
- }
82
- return null;
83
- }));
76
+ const [first] = yield* drain();
77
+ if (first) {
78
+ const dec = yield* decodeDrain(first);
79
+ const { createdAt, updatedAt, ...rest } = dec;
80
+ yield* drainRepo.update(Drain.update.make({ ...rest, processingAt: Option.some(new Date()) }) // auto in lib , etag: randomUUID()
81
+ );
82
+ return dec;
83
+ }
84
84
  if (first)
85
85
  return first;
86
86
  yield* Effect.sleep(250);
87
87
  }
88
88
  }),
89
- finish: ({ createdAt, updatedAt, ...q }) => drainRepo.update(Drain.update.make({ ...q, finishedAt: Option.some(new Date()) }))
89
+ finish: ({ createdAt, updatedAt, ...q }) => drainRepo.update(Drain.update.make({ ...q, finishedAt: Option.some(new Date()) })) // auto in lib , etag: randomUUID()
90
90
  };
91
91
  const rcc = yield* RequestContextContainer;
92
92
  return {
@@ -141,4 +141,4 @@ export function makeSQLQueue(queueName, queueDrainName, schema, drainSchema) {
141
141
  };
142
142
  });
143
143
  }
144
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU1FMUXVldWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvUXVldWVNYWtlci9TUUxRdWV1ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQTtBQUN4RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sa0NBQWtDLENBQUE7QUFDakUsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sOENBQThDLENBQUE7QUFFMUYsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLCtDQUErQyxDQUFBO0FBQ3pFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9EQUFvRCxDQUFBO0FBQzVGLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFDckMsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDN0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBQzFDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFFN0MsTUFBTSxDQUFDLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQTtBQUd4RDs7R0FFRztBQUNILE1BQU0sVUFBVSxZQUFZLENBTTFCLFNBQTRCLEVBQzVCLGNBQWlDLEVBQ2pDLE1BQTJCLEVBQzNCLFdBQTBDO0lBRTFDLE9BQU8sTUFBTSxDQUFD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
144
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU1FMUXVldWUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvUXVldWVNYWtlci9TUUxRdWV1ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sZ0NBQWdDLENBQUE7QUFDdEQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sb0NBQW9DLENBQUE7QUFDeEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtDQUFrQyxDQUFBO0FBQ2pFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLDhDQUE4QyxDQUFBO0FBRTFGLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQTtBQUN6RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvREFBb0QsQ0FBQTtBQUM1RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3ZDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDbkMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUNyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUM3RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFDMUMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUU3QyxNQUFNLENBQUMsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFBO0FBR3hELG9GQUFvRjtBQUNwRixNQUFNLFVB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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effect-app/infra",
3
- "version": "1.23.4",
3
+ "version": "1.24.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -19,8 +19,8 @@
19
19
  "pure-rand": "6.1.0",
20
20
  "redlock": "^4.2.0",
21
21
  "@effect-app/core": "1.10.2",
22
+ "@effect-app/infra-adapters": "1.12.0",
22
23
  "effect-app": "1.17.5",
23
- "@effect-app/infra-adapters": "1.11.7",
24
24
  "@effect-app/schema": "1.12.2"
25
25
  },
26
26
  "devDependencies": {
@@ -1,10 +1,12 @@
1
+ import { Model } from "@effect-app/infra-adapters/SQL"
1
2
  import { setupRequestContext } from "@effect-app/infra/api/setupRequest"
2
3
  import { RequestContext } from "@effect-app/infra/RequestContext"
3
4
  import { reportNonInterruptedFailure } from "@effect-app/infra/services/QueueMaker/errors"
4
5
  import type { QueueBase } from "@effect-app/infra/services/QueueMaker/service"
5
6
  import { QueueMeta } from "@effect-app/infra/services/QueueMaker/service"
6
7
  import { RequestContextContainer } from "@effect-app/infra/services/RequestContextContainer"
7
- import { Model, SqlClient } from "@effect/sql"
8
+ import { SqlClient } from "@effect/sql"
9
+ import { randomUUID } from "crypto"
8
10
  import { subMinutes } from "date-fns"
9
11
  import { Effect, Fiber, Option, S, Tracer } from "effect-app"
10
12
  import { RequestId } from "effect-app/ids"
@@ -15,9 +17,7 @@ import { InfraLogger } from "../../logger.js"
15
17
  export const QueueId = S.Number.pipe(S.brand("QueueId"))
16
18
  export type QueueId = typeof QueueId.Type
17
19
 
18
- /**
19
- * Currently limited to one process draining at a time, due to in-process Semaphore instead of row-level locking.
20
- */
20
+ // TODO: let the model track and Auto Generate versionColumn on every update instead
21
21
  export function makeSQLQueue<
22
22
  Evt extends { id: S.StringId; _tag: string },
23
23
  DrainEvt extends { id: S.StringId; _tag: string },
@@ -38,7 +38,8 @@ export function makeSQLQueue<
38
38
  updatedAt: Model.DateTimeUpdate,
39
39
  // TODO: at+owner
40
40
  processingAt: Model.FieldOption(S.Date),
41
- finishedAt: Model.FieldOption(S.Date)
41
+ finishedAt: Model.FieldOption(S.Date),
42
+ etag: S.String // TODO: use a Model thing that auto updates it?
42
43
  // TODO: record locking.. / optimistic locking
43
44
  // rowVersion: Model.DateTimeFromNumberWithNow
44
45
  }
@@ -55,13 +56,15 @@ export function makeSQLQueue<
55
56
  const queueRepo = yield* Model.makeRepository(Queue, {
56
57
  tableName: "queue",
57
58
  spanPrefix: "QueueRepo",
58
- idColumn: "id"
59
+ idColumn: "id",
60
+ versionColumn: "etag"
59
61
  })
60
62
 
61
63
  const drainRepo = yield* Model.makeRepository(Drain, {
62
64
  tableName: "queue",
63
65
  spanPrefix: "DrainRepo",
64
- idColumn: "id"
66
+ idColumn: "id",
67
+ versionColumn: "etag"
65
68
  })
66
69
 
67
70
  const decodeDrain = S.decode(Drain)
@@ -74,9 +77,6 @@ export function makeSQLQueue<
74
77
  LIMIT 1`
75
78
  }
76
79
 
77
- // temporary workaround until we have a SQLite rowversion..
78
- const lock = yield* Effect.makeSemaphore(1)
79
-
80
80
  const q = {
81
81
  offer: (body: Evt, meta: typeof QueueMeta.Type) =>
82
82
  Effect.gen(function*() {
@@ -86,28 +86,28 @@ export function makeSQLQueue<
86
86
  meta,
87
87
  name: queueName,
88
88
  processingAt: Option.none(),
89
- finishedAt: Option.none()
89
+ finishedAt: Option.none(),
90
+ etag: randomUUID()
90
91
  })
91
92
  )
92
93
  }),
93
94
  take: Effect.gen(function*() {
94
95
  while (true) {
95
- const first = yield* lock.withPermits(1)(Effect.gen(function*() {
96
- const [first] = yield* drain()
97
- if (first) {
98
- const dec = yield* decodeDrain(first)
99
- const { createdAt, updatedAt, ...rest } = dec
100
- yield* drainRepo.update(Drain.update.make({ ...rest, processingAt: Option.some(new Date()) }))
101
- return dec
102
- }
103
- return null
104
- }))
96
+ const [first] = yield* drain()
97
+ if (first) {
98
+ const dec = yield* decodeDrain(first)
99
+ const { createdAt, updatedAt, ...rest } = dec
100
+ yield* drainRepo.update(
101
+ Drain.update.make({ ...rest, processingAt: Option.some(new Date()) }) // auto in lib , etag: randomUUID()
102
+ )
103
+ return dec
104
+ }
105
105
  if (first) return first
106
106
  yield* Effect.sleep(250)
107
107
  }
108
108
  }),
109
109
  finish: ({ createdAt, updatedAt, ...q }: Drain) =>
110
- drainRepo.update(Drain.update.make({ ...q, finishedAt: Option.some(new Date()) }))
110
+ drainRepo.update(Drain.update.make({ ...q, finishedAt: Option.some(new Date()) })) // auto in lib , etag: randomUUID()
111
111
  }
112
112
  const rcc = yield* RequestContextContainer
113
113
 
package/tsconfig.src.json CHANGED
@@ -6,7 +6,6 @@
6
6
  ],
7
7
  "tsBuildInfoFile": "./dist/.tsbuildinfo",
8
8
  "esModuleInterop": true,
9
- "baseUrl": "./",
10
9
  "rootDir": "./src",
11
10
  // keep in here, cause madge can't detect it from extended tsconfig
12
11
  "moduleResolution": "Node16",
@@ -2,7 +2,6 @@
2
2
  "extends": "./tsconfig.src.json",
3
3
  "compilerOptions": {
4
4
  "rootDir": "./test",
5
- "baseUrl": "./test",
6
5
  "outDir": "./test/dist",
7
6
  "tsBuildInfoFile": "./test/dist/.tsbuildinfo",
8
7
  // "types": [
@@ -0,0 +1,37 @@
1
+ // packages/infra/vitest.config.ts
2
+ import { defineConfig } from "file:///Users/patrickroza/pj/effect-app/libs/node_modules/.pnpm/vite@5.2.6_@types+node@20.11.30/node_modules/vite/dist/node/index.js";
3
+
4
+ // vite.config.base.ts
5
+ import path from "path";
6
+ import fs from "fs";
7
+ var __vite_injected_original_dirname = "/Users/patrickroza/pj/effect-app/libs";
8
+ function makeConfig(dirName) {
9
+ const prefix = path.resolve(__vite_injected_original_dirname, "packages");
10
+ const packages = fs.readdirSync(prefix).map((f) => prefix + "/" + f).filter((f) => fs.lstatSync(f).isDirectory());
11
+ const cfg = {
12
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
13
+ //plugins: [autoImport],
14
+ test: {
15
+ include: ["./test/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
16
+ reporters: "verbose",
17
+ globals: true
18
+ },
19
+ resolve: {
20
+ alias: packages.reduce((acc, cur) => {
21
+ acc[JSON.parse(fs.readFileSync(cur + "/package.json", "utf-8")).name] = path.resolve(cur, cur.endsWith("core") ? "dist" : "src");
22
+ return acc;
23
+ }, {})
24
+ // "@effect-app/core/Prelude": path.join(__dirname, "packages/core/src/Prelude.code.ts")
25
+ }
26
+ };
27
+ console.log(cfg);
28
+ return cfg;
29
+ }
30
+
31
+ // packages/infra/vitest.config.ts
32
+ var __vite_injected_original_dirname2 = "/Users/patrickroza/pj/effect-app/libs/packages/infra";
33
+ var vitest_config_default = defineConfig(makeConfig(__vite_injected_original_dirname2));
34
+ export {
35
+ vitest_config_default as default
36
+ };
37
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50cyIsICJ2aXRlLmNvbmZpZy5iYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy9wYWNrYWdlcy9pbmZyYS92aXRlc3QuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvcGFja2FnZXMvaW5mcmEvdml0ZXN0LmNvbmZpZy50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gXCJ2aXRlXCJcbmltcG9ydCBtYWtlQ29uZmlnIGZyb20gXCIuLi8uLi92aXRlLmNvbmZpZy5iYXNlXCJcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKG1ha2VDb25maWcoX19kaXJuYW1lKSlcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlic1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL3BhdHJpY2tyb3phL3BqL2VmZmVjdC1hcHAvbGlicy92aXRlLmNvbmZpZy5iYXNlLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9wYXRyaWNrcm96YS9wai9lZmZlY3QtYXBwL2xpYnMvdml0ZS5jb25maWcuYmFzZS50c1wiOy8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZXN0XCIgLz5cbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCJcbmltcG9ydCBmcyBmcm9tIFwiZnNcIlxuaW1wb3J0IEF1dG9JbXBvcnQgZnJvbSBcInVucGx1Z2luLWF1dG8taW1wb3J0L3ZpdGVcIlxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVzdC9jb25maWdcIlxuXG4vLyBjb25zdCBhdXRvSW1wb3J0ID0gQXV0b0ltcG9ydCh7XG4vLyAgIGR0czogXCIuL3Rlc3QvYXV0by1pbXBvcnRzLmQudHNcIixcbi8vICAgLy8gaW5jbHVkZTogW1xuLy8gICAvLyAgIC9cXC50ZXN0XFwuW3RqXXN4PyQvIC8vIC50cywgLnRzeCwgLmpzLCAuanN4XG4vLyAgIC8vIF0sXG4vLyAgIGltcG9ydHM6IFtcbi8vICAgICBcInZpdGVzdFwiXG4vLyAgIF1cbi8vIH0pXG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIG1ha2VDb25maWcoZGlyTmFtZT86IHN0cmluZykge1xuICBjb25zdCBwcmVmaXggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCBcInBhY2thZ2VzXCIpXG4gIGNvbnN0IHBhY2thZ2VzID0gZnMucmVhZGRpclN5bmMocHJlZml4KS5tYXAoZiA9PiBwcmVmaXggKyBcIi9cIiArIGYpLmZpbHRlcihmID0+IGZzLmxzdGF0U3luYyhmKS5pc0RpcmVjdG9yeSgpIClcbiAgY29uc3QgY2ZnID0ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG4gICAgLy9wbHVnaW5zOiBbYXV0b0ltcG9ydF0sXG4gICAgdGVzdDoge1xuICAgICAgaW5jbHVkZTogIFtcIi4vdGVzdC8qKi8qLnRlc3Que2pzLG1qcyxjanMsdHMsbXRzLGN0cyxqc3gsdHN4fVwiXSxcbiAgICAgIHJlcG9ydGVyczogXCJ2ZXJib3NlXCIsXG4gICAgICBnbG9iYWxzOiB0cnVlXG4gICAgfSxcbiAgICByZXNvbHZlOiB7XG4gICAgICBhbGlhczogcGFja2FnZXMucmVkdWNlKChhY2MsIGN1cikgPT4geyAvLyB3b3JrYXJvdW5kIGZvciAvUHJlbHVkZSBpc3N1ZVxuICAgICAgYWNjW0pTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGN1ciArIFwiL3BhY2thZ2UuanNvblwiLCBcInV0Zi04XCIpKS5uYW1lXSA9IHBhdGgucmVzb2x2ZShjdXIsIGN1ci5lbmRzV2l0aChcImNvcmVcIikgPyBcImRpc3RcIiA6IFwic3JjXCIpXG4gICAgICByZXR1cm4gYWNjXG4gICAgfSwgeyB9KSAvLyBcIkBlZmZlY3QtYXBwL2NvcmUvUHJlbHVkZVwiOiBwYXRoLmpvaW4oX19kaXJuYW1lLCBcInBhY2thZ2VzL2NvcmUvc3JjL1ByZWx1ZGUuY29kZS50c1wiKVxuICB9XG4gIH1cbiAgY29uc29sZS5sb2coY2ZnKVxuICByZXR1cm4gY2ZnXG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQ0EsU0FBUyxvQkFBb0I7OztBQ0E3QixPQUFPLFVBQVU7QUFDakIsT0FBTyxRQUFRO0FBRmYsSUFBTSxtQ0FBbUM7QUFnQjFCLFNBQVIsV0FBNEIsU0FBa0I7QUFDbkQsUUFBTSxTQUFTLEtBQUssUUFBUSxrQ0FBVyxVQUFVO0FBQ2pELFFBQU0sV0FBVyxHQUFHLFlBQVksTUFBTSxFQUFFLElBQUksT0FBSyxTQUFTLE1BQU0sQ0FBQyxFQUFFLE9BQU8sT0FBSyxHQUFHLFVBQVUsQ0FBQyxFQUFFLFlBQVksQ0FBRTtBQUM3RyxRQUFNLE1BQU07QUFBQTtBQUFBO0FBQUEsSUFHVixNQUFNO0FBQUEsTUFDSixTQUFVLENBQUMsa0RBQWtEO0FBQUEsTUFDN0QsV0FBVztBQUFBLE1BQ1gsU0FBUztBQUFBLElBQ1g7QUFBQSxJQUNBLFNBQVM7QUFBQSxNQUNQLE9BQU8sU0FBUyxPQUFPLENBQUMsS0FBSyxRQUFRO0FBQ3JDLFlBQUksS0FBSyxNQUFNLEdBQUcsYUFBYSxNQUFNLGlCQUFpQixPQUFPLENBQUMsRUFBRSxJQUFJLElBQUksS0FBSyxRQUFRLEtBQUssSUFBSSxTQUFTLE1BQU0sSUFBSSxTQUFTLEtBQUs7QUFDL0gsZUFBTztBQUFBLE1BQ1QsR0FBRyxDQUFFLENBQUM7QUFBQTtBQUFBLElBQ1I7QUFBQSxFQUNBO0FBQ0EsVUFBUSxJQUFJLEdBQUc7QUFDZixTQUFPO0FBQ1Q7OztBRHBDQSxJQUFNQSxvQ0FBbUM7QUFJekMsSUFBTyx3QkFBUSxhQUFhLFdBQVdDLGlDQUFTLENBQUM7IiwKICAibmFtZXMiOiBbIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIiwgIl9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lIl0KfQo=