@xyo-network/image-thumbnail-plugin 2.75.6 → 2.75.8

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.
@@ -40,6 +40,7 @@ export declare class ImageThumbnailDiviner<TParams extends ImageThumbnailDiviner
40
40
  * preemptions, reboots, etc.
41
41
  */
42
42
  protected retrieveState(): Promise<ImageThumbnailDivinerState | undefined>;
43
+ protected startHandler(): Promise<boolean>;
43
44
  protected stopHandler(_timeout?: number | undefined): Promise<boolean>;
44
45
  private poll;
45
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA0DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YAQvE,IAAI;CASnB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA2DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAMvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;cAMhC,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrF,OAAO,CAAC,IAAI;CAab"}
@@ -40,6 +40,7 @@ export declare class ImageThumbnailDiviner<TParams extends ImageThumbnailDiviner
40
40
  * preemptions, reboots, etc.
41
41
  */
42
42
  protected retrieveState(): Promise<ImageThumbnailDivinerState | undefined>;
43
+ protected startHandler(): Promise<boolean>;
43
44
  protected stopHandler(_timeout?: number | undefined): Promise<boolean>;
44
45
  private poll;
45
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA0DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YAQvE,IAAI;CASnB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA2DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAMvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;cAMhC,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrF,OAAO,CAAC,IAAI;CAab"}
@@ -40,6 +40,7 @@ export declare class ImageThumbnailDiviner<TParams extends ImageThumbnailDiviner
40
40
  * preemptions, reboots, etc.
41
41
  */
42
42
  protected retrieveState(): Promise<ImageThumbnailDivinerState | undefined>;
43
+ protected startHandler(): Promise<boolean>;
43
44
  protected stopHandler(_timeout?: number | undefined): Promise<boolean>;
44
45
  private poll;
45
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA0DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;YAQvE,IAAI;CASnB"}
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../../src/Diviner/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAMjE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAG7D,OAAO,EAAyB,OAAO,EAAE,MAAM,4BAA4B,CAAA;AAI3E,OAAO,EAAE,2BAA2B,EAAqC,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAA;AAUtD,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAA;CACf;AASD,KAAK,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,gBAAgB,CAAA;AAEpE,KAAK,WAAW,GAAG,OAAO,CAAC,MAAM,2BAA2B,EAAE,cAAc,CAAC,CAAA;AAE7E,QAAA,MAAM,+BAA+B,qCAA2C,CAAA;AAChF,KAAK,+BAA+B,GAAG,OAAO,+BAA+B,CAAA;AAE7E,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,EAAE,CAAA;IAEjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,KAAK,oBAAoB,GAAG,OAAO,CAAC,wBAAwB,EAAE,+BAA+B,CAAC,CAAA;AAmB9F,qBAAa,qBAAqB,CAAC,OAAO,SAAS,2BAA2B,GAAG,2BAA2B,CAAE,SAAQ,eAAe,CAAC,OAAO,CAAC;IAC5I,OAAgB,aAAa,kFAA2D;IAExF,OAAO,CAAC,OAAO,CAAC,CAAkC;IAElD,IAAI,mBAAmB,WAEtB;IAED,IAAI,aAAa,WAEhB;IAED,SAAS,CAAC,gBAAgB,QAAa,QAAQ,IAAI,CAAC,CA2DnD;IAED;;;;;OAKG;cACa,WAAW,CAAC,KAAK,EAAE,0BAA0B;cAUpC,aAAa,CAAC,QAAQ,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;cAmBjF,oBAAoB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAMvD,8BAA8B,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;cAQjE,yBAAyB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,OAAO;IAM5E;;;OAGG;cACa,aAAa,IAAI,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC;cA8CvD,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;cAMhC,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAQrF,OAAO,CAAC,IAAI;CAab"}
@@ -73,15 +73,15 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
73
73
  if (batch.length === 0)
74
74
  return;
75
75
  const imageThumbnailTimestampTuples = batch.filter(import_boundwitness_model.isBoundWitness).map((bw) => {
76
- var _a, _b, _c, _d;
77
- const imageThumbnailIndex = (_a = bw.payload_schemas) == null ? void 0 : _a.findIndex((schema) => schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema);
76
+ var _a, _b, _c;
77
+ const imageThumbnailIndexes = (_a = bw.payload_schemas) == null ? void 0 : _a.map((schema, index) => schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema ? index : void 0).filter(import_exists.exists);
78
78
  const timestampIndex = (_b = bw.payload_schemas) == null ? void 0 : _b.findIndex((schema) => schema === import_witness_timestamp.TimestampSchema);
79
- if (!imageThumbnailIndex || !timestampIndex)
79
+ if (!imageThumbnailIndexes.length || timestampIndex === -1)
80
80
  return void 0;
81
- const imageThumbnail = (_c = bw.payload_hashes) == null ? void 0 : _c[imageThumbnailIndex];
82
- const timestamp = (_d = bw.payload_hashes) == null ? void 0 : _d[timestampIndex];
83
- return [imageThumbnail, timestamp];
84
- }).filter(import_exists.exists);
81
+ const imageThumbnails = bw.payload_hashes.map((hash, index) => imageThumbnailIndexes.includes(index) ? hash : void 0).filter(import_exists.exists);
82
+ const timestamp = (_c = bw.payload_hashes) == null ? void 0 : _c[timestampIndex];
83
+ return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp]);
84
+ }).flat().filter(import_exists.exists);
85
85
  const archivist = await this.getArchivistForStore("thumbnailStore");
86
86
  const payloadTuples = (await Promise.all(
87
87
  imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {
@@ -99,7 +99,7 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
99
99
  )).filter(import_exists.exists);
100
100
  const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {
101
101
  var _a;
102
- const { url } = thumbnailPayload;
102
+ const { sourceUrl: url } = thumbnailPayload;
103
103
  const { timestamp } = timestampPayload;
104
104
  const status = ((_a = thumbnailPayload.http) == null ? void 0 : _a.status) ?? -1;
105
105
  const sources = [thumbnailHash, timestampHash];
@@ -141,9 +141,9 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
141
141
  }
142
142
  async getArchivistForStore(store, wrap) {
143
143
  var _a, _b;
144
- const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.archivist not specified`);
144
+ const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`);
145
145
  const mod = (0, import_assert.assertEx)(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`);
146
- return wrap ? import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account) : (0, import_archivist_model.asArchivistInstance)(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not an Archivist`);
146
+ return wrap ? import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account) : (0, import_archivist_model.asArchivistInstance)(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`);
147
147
  }
148
148
  async getBoundWitnessDivinerForStore(store, wrap) {
149
149
  var _a, _b;
@@ -165,12 +165,12 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
165
165
  var _a;
166
166
  let hash = "";
167
167
  const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
168
- const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_payload_model.PayloadDivinerQuerySchema }).fields({
168
+ const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_boundwitness_model.BoundWitnessDivinerQuerySchema }).fields({
169
169
  address: this.account.address,
170
170
  limit: 1,
171
171
  offset: 0,
172
172
  order: "desc",
173
- schemas: [import_image_thumbnail_payload_plugin2.ImageThumbnailSchema]
173
+ payload_schemas: [ModuleStateSchema]
174
174
  });
175
175
  const boundWitnesses = await diviner.divine([query]);
176
176
  if (boundWitnesses.length > 0) {
@@ -203,6 +203,11 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
203
203
  }
204
204
  return void 0;
205
205
  }
206
+ async startHandler() {
207
+ await super.startHandler();
208
+ this.poll();
209
+ return true;
210
+ }
206
211
  async stopHandler(_timeout) {
207
212
  if (this._pollId) {
208
213
  clearTimeout(this._pollId);
@@ -210,14 +215,19 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
210
215
  }
211
216
  return await super.stopHandler();
212
217
  }
213
- async poll() {
214
- if (await this.started()) {
215
- this._pollId = setTimeout(async () => {
216
- this._pollId = void 0;
218
+ poll() {
219
+ this._pollId = setTimeout(async () => {
220
+ try {
217
221
  await this.backgroundDivine();
218
- await this.poll();
219
- }, this.pollFrequency);
220
- }
222
+ } catch (e) {
223
+ console.log(e);
224
+ } finally {
225
+ if (this._pollId)
226
+ clearTimeout(this._pollId);
227
+ this._pollId = void 0;
228
+ this.poll();
229
+ }
230
+ }, this.pollFrequency);
221
231
  }
222
232
  };
223
233
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/Diviner/Diviner.ts","../../../src/Diviner/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { asArchivistInstance, withArchivistModule } from '@xyo-network/archivist-model'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance, DivinerConfigSchema } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { ImageThumbnailSchema, isImageThumbnail } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'\nimport { isUrlPayload } from '@xyo-network/url-payload-plugin'\nimport { isTimestamp, TimestampSchema } from '@xyo-network/witness-timestamp'\n\nimport { ImageThumbnailDivinerConfig, ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\n/**\n * TODO: Once the shape settles, make a generic payload so that it\n * can be used for other modules\n */\ninterface State<T> {\n state: T\n}\n\ninterface ImageThumbnailDivinerState {\n offset: number\n}\n\nconst ModuleStateSchema = 'network.xyo.module.state' as const\ntype ModuleStateSchema = typeof ModuleStateSchema\n\ntype ModuleState = Payload<State<ImageThumbnailDivinerState>, ModuleStateSchema>\n\nconst isModuleState = isPayloadOfSchemaType<ModuleState>(ModuleStateSchema)\n\ntype ConfigStoreKey = 'indexStore' | 'stateStore' | 'thumbnailStore'\n\ntype ConfigStore = Extract<keyof ImageThumbnailDivinerConfig, ConfigStoreKey>\n\nconst ImageThumbnailResultIndexSchema = `${ImageThumbnailSchema}.index` as const\ntype ImageThumbnailResultIndexSchema = typeof ImageThumbnailResultIndexSchema\n\ninterface ImageThumbnailResultInfo {\n sources: string[]\n // TODO: Something richer than HTTP status code that allows for info about failure modes\n status: number\n timestamp: number\n url: string\n}\n\ntype ImageThumbnailResult = Payload<ImageThumbnailResultInfo, ImageThumbnailResultIndexSchema>\n\nconst isImageThumbnailResult = isPayloadOfSchemaType<ImageThumbnailResult>(ImageThumbnailResultIndexSchema)\n\n/**\n * The fields that will need to be indexed on in the underlying store\n */\ntype QueryableImageThumbnailResultProperties = Extract<keyof ImageThumbnailResult, 'url' | 'timestamp' | 'status'>\n\n/**\n * The query that will be used to retrieve the results from the underlying store\n */\ntype ImageThumbnailResultQuery = PayloadDivinerQueryPayload & { schemas: [ImageThumbnailSchema] } & Pick<\n ImageThumbnailResult,\n QueryableImageThumbnailResultProperties\n >\n\nconst moduleName = 'ImageThumbnailDiviner'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _pollId?: string | number | NodeJS.Timeout\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1_0000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = (await this.retrieveState()) ?? { offset: 0 }\n const { offset } = lastState\n // Get next batch of results\n const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore('thumbnailStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n limit: this.payloadDivinerLimit,\n offset,\n order: 'asc',\n payload_schemas: [ImageThumbnailSchema, TimestampSchema],\n })\n const batch = await boundWitnessDiviner.divine([query])\n if (batch.length === 0) return\n const imageThumbnailTimestampTuples = batch\n .filter(isBoundWitness)\n .map((bw) => {\n const imageThumbnailIndex = bw.payload_schemas?.findIndex((schema) => schema === ImageThumbnailSchema)\n const timestampIndex = bw.payload_schemas?.findIndex((schema) => schema === TimestampSchema)\n if (!imageThumbnailIndex || !timestampIndex) return undefined\n const imageThumbnail = bw.payload_hashes?.[imageThumbnailIndex]\n const timestamp = bw.payload_hashes?.[timestampIndex]\n return [imageThumbnail, timestamp] as const\n })\n .filter(exists)\n const archivist = await this.getArchivistForStore('thumbnailStore')\n const payloadTuples = (\n await Promise.all(\n imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {\n const results = await archivist.get([imageThumbnailHash, timestampHash])\n const imageThumbnailPayload = results.find(isImageThumbnail)\n const timestampPayload = results.find(isTimestamp)\n if (!imageThumbnailPayload || !timestampPayload) return undefined\n const calculatedImageThumbnailHash = await PayloadHasher.hashAsync(imageThumbnailPayload)\n const calculatedTimestampHash = await PayloadHasher.hashAsync(timestampPayload)\n if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash) return undefined\n return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload] as const\n }),\n )\n ).filter(exists)\n // Build index results\n const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {\n const { url } = thumbnailPayload\n const { timestamp } = timestampPayload\n const status = thumbnailPayload.http?.status ?? -1\n const sources = [thumbnailHash, timestampHash]\n const result = new PayloadBuilder<ImageThumbnailResult>({ schema: ImageThumbnailResultIndexSchema })\n .fields({ sources, status, timestamp, url })\n .build()\n return result\n })\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexedResults)\n // Update state\n const nextOffset = offset + batch.length + 1\n const currentState = { ...lastState, offset: nextOffset }\n await this.commitState(currentState)\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n */\n protected async commitState(state: ImageThumbnailDivinerState) {\n const stateStore = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore configured`)\n const module = assertEx(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`)\n await withArchivistModule(module, async (archivist) => {\n const mod = ArchivistWrapper.wrap(archivist, this.account)\n const payload = new PayloadBuilder<ModuleState>({ schema: ModuleStateSchema }).fields({ state }).build()\n await mod.insert([payload])\n })\n }\n\n protected override async divineHandler(payloads: Payload[] = []): Promise<ImageThumbnailResult[]> {\n const urls = payloads.filter(isUrlPayload).map((urlPayload) => urlPayload.url)\n const diviner = await this.getPayloadDivinerForStore('indexStore')\n const results = (\n await Promise.all(\n urls.map(async (url) => {\n const query = new PayloadBuilder<ImageThumbnailResultQuery>({ schema: PayloadDivinerQuerySchema })\n // TODO: Expose status, limit (and possibly offset) to caller. Currently only exposing URL\n .fields({ limit: 1, offset: 0, order: 'desc', url })\n .build()\n return await diviner.divine([query])\n }),\n )\n )\n .flat()\n .filter(isImageThumbnailResult)\n return results\n }\n\n protected async getArchivistForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`)\n return wrap\n ? ArchivistWrapper.wrap(mod, this.account)\n : asArchivistInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not an Archivist`)\n }\n\n protected async getBoundWitnessDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`)\n return wrap\n ? DivinerWrapper.wrap(mod, this.account)\n : asDivinerInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`)\n }\n\n protected async getPayloadDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`)\n return wrap ? DivinerWrapper.wrap(mod, this.account) : asDivinerInstance(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ImageThumbnailDivinerState | undefined> {\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = new PayloadBuilder<PayloadDivinerQueryPayload>({ schema: PayloadDivinerQuerySchema }).fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n schemas: [ImageThumbnailSchema],\n })\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const stateStoreArchivist = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore archivist configured`)\n await withArchivistModule(\n assertEx(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),\n async (mod) => {\n const archivist = ArchivistWrapper.wrap(mod, this.account)\n const payloads = await archivist.get([hash])\n if (payloads.length > 0) {\n const payload = payloads[0]\n if (isModuleState(payload)) {\n return payload.state\n }\n }\n },\n )\n }\n return undefined\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private async poll() {\n if (await this.started()) {\n this._pollId = setTimeout(async () => {\n this._pollId = undefined\n await this.backgroundDivine()\n await this.poll()\n }, this.pollFrequency)\n }\n }\n}\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\n/**\n * Describes an Archivist/Diviner combination\n * that enables searching signed payloads\n */\nexport interface SearchableStorage {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n}\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n /** @deprecated Use appropriate Storage */\n archivist?: string\n /**\n * Where the diviner should store it's index\n */\n indexStore?: SearchableStorage\n /** @deprecated Use appropriate Storage */\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n /**\n * Where the diviner should persist its internal state\n */\n stateStore?: SearchableStorage\n /**\n * Where the diviner should look for stored thumbnails\n */\n thumbnailStore?: SearchableStorage\n}>\n"],"mappings":"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","names":["import_image_thumbnail_payload_plugin","module","_a"]}
1
+ {"version":3,"sources":["../../../src/Diviner/Diviner.ts","../../../src/Diviner/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { asArchivistInstance, withArchivistModule } from '@xyo-network/archivist-model'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance, DivinerConfigSchema } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { ImageThumbnailSchema, isImageThumbnail } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'\nimport { isUrlPayload } from '@xyo-network/url-payload-plugin'\nimport { isTimestamp, TimestampSchema } from '@xyo-network/witness-timestamp'\n\nimport { ImageThumbnailDivinerConfig, ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\n/**\n * TODO: Once the shape settles, make a generic payload so that it\n * can be used for other modules\n */\ninterface State<T> {\n state: T\n}\n\ninterface ImageThumbnailDivinerState {\n offset: number\n}\n\nconst ModuleStateSchema = 'network.xyo.module.state' as const\ntype ModuleStateSchema = typeof ModuleStateSchema\n\ntype ModuleState = Payload<State<ImageThumbnailDivinerState>, ModuleStateSchema>\n\nconst isModuleState = isPayloadOfSchemaType<ModuleState>(ModuleStateSchema)\n\ntype ConfigStoreKey = 'indexStore' | 'stateStore' | 'thumbnailStore'\n\ntype ConfigStore = Extract<keyof ImageThumbnailDivinerConfig, ConfigStoreKey>\n\nconst ImageThumbnailResultIndexSchema = `${ImageThumbnailSchema}.index` as const\ntype ImageThumbnailResultIndexSchema = typeof ImageThumbnailResultIndexSchema\n\ninterface ImageThumbnailResultInfo {\n sources: string[]\n // TODO: Something richer than HTTP status code that allows for info about failure modes\n status: number\n timestamp: number\n url: string\n}\n\ntype ImageThumbnailResult = Payload<ImageThumbnailResultInfo, ImageThumbnailResultIndexSchema>\n\nconst isImageThumbnailResult = isPayloadOfSchemaType<ImageThumbnailResult>(ImageThumbnailResultIndexSchema)\n\n/**\n * The fields that will need to be indexed on in the underlying store\n */\ntype QueryableImageThumbnailResultProperties = Extract<keyof ImageThumbnailResult, 'url' | 'timestamp' | 'status'>\n\n/**\n * The query that will be used to retrieve the results from the underlying store\n */\ntype ImageThumbnailResultQuery = PayloadDivinerQueryPayload & { schemas: [ImageThumbnailSchema] } & Pick<\n ImageThumbnailResult,\n QueryableImageThumbnailResultProperties\n >\n\nconst moduleName = 'ImageThumbnailDiviner'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _pollId?: string | number | NodeJS.Timeout\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1_0000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = (await this.retrieveState()) ?? { offset: 0 }\n const { offset } = lastState\n // Get next batch of results\n const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore('thumbnailStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n limit: this.payloadDivinerLimit,\n offset,\n order: 'asc',\n payload_schemas: [ImageThumbnailSchema, TimestampSchema],\n })\n const batch = await boundWitnessDiviner.divine([query])\n if (batch.length === 0) return\n const imageThumbnailTimestampTuples = batch\n .filter(isBoundWitness)\n .map((bw) => {\n const imageThumbnailIndexes = bw.payload_schemas?.map((schema, index) => (schema === ImageThumbnailSchema ? index : undefined)).filter(exists)\n const timestampIndex = bw.payload_schemas?.findIndex((schema) => schema === TimestampSchema)\n if (!imageThumbnailIndexes.length || timestampIndex === -1) return undefined\n const imageThumbnails = bw.payload_hashes.map((hash, index) => (imageThumbnailIndexes.includes(index) ? hash : undefined)).filter(exists)\n const timestamp = bw.payload_hashes?.[timestampIndex]\n return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp] as const)\n })\n .flat()\n .filter(exists)\n const archivist = await this.getArchivistForStore('thumbnailStore')\n const payloadTuples = (\n await Promise.all(\n imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {\n const results = await archivist.get([imageThumbnailHash, timestampHash])\n const imageThumbnailPayload = results.find(isImageThumbnail)\n const timestampPayload = results.find(isTimestamp)\n if (!imageThumbnailPayload || !timestampPayload) return undefined\n const calculatedImageThumbnailHash = await PayloadHasher.hashAsync(imageThumbnailPayload)\n const calculatedTimestampHash = await PayloadHasher.hashAsync(timestampPayload)\n if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash) return undefined\n return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload] as const\n }),\n )\n ).filter(exists)\n // Build index results\n const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {\n const { sourceUrl: url } = thumbnailPayload\n const { timestamp } = timestampPayload\n const status = thumbnailPayload.http?.status ?? -1\n const sources = [thumbnailHash, timestampHash]\n const result = new PayloadBuilder<ImageThumbnailResult>({ schema: ImageThumbnailResultIndexSchema })\n .fields({ sources, status, timestamp, url })\n .build()\n return result\n })\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexedResults)\n // Update state\n const nextOffset = offset + batch.length + 1\n const currentState = { ...lastState, offset: nextOffset }\n await this.commitState(currentState)\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n */\n protected async commitState(state: ImageThumbnailDivinerState) {\n const stateStore = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore configured`)\n const module = assertEx(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`)\n await withArchivistModule(module, async (archivist) => {\n const mod = ArchivistWrapper.wrap(archivist, this.account)\n const payload = new PayloadBuilder<ModuleState>({ schema: ModuleStateSchema }).fields({ state }).build()\n await mod.insert([payload])\n })\n }\n\n protected override async divineHandler(payloads: Payload[] = []): Promise<ImageThumbnailResult[]> {\n const urls = payloads.filter(isUrlPayload).map((urlPayload) => urlPayload.url)\n const diviner = await this.getPayloadDivinerForStore('indexStore')\n const results = (\n await Promise.all(\n urls.map(async (url) => {\n const query = new PayloadBuilder<ImageThumbnailResultQuery>({ schema: PayloadDivinerQuerySchema })\n // TODO: Expose status, limit (and possibly offset) to caller. Currently only exposing URL\n .fields({ limit: 1, offset: 0, order: 'desc', url })\n .build()\n return await diviner.divine([query])\n }),\n )\n )\n .flat()\n .filter(isImageThumbnailResult)\n return results\n }\n\n protected async getArchivistForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`)\n return wrap ? ArchivistWrapper.wrap(mod, this.account) : asArchivistInstance(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`)\n }\n\n protected async getBoundWitnessDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`)\n return wrap\n ? DivinerWrapper.wrap(mod, this.account)\n : asDivinerInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`)\n }\n\n protected async getPayloadDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`)\n return wrap ? DivinerWrapper.wrap(mod, this.account) : asDivinerInstance(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ImageThumbnailDivinerState | undefined> {\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const stateStoreArchivist = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore archivist configured`)\n await withArchivistModule(\n assertEx(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),\n async (mod) => {\n const archivist = ArchivistWrapper.wrap(mod, this.account)\n const payloads = await archivist.get([hash])\n if (payloads.length > 0) {\n const payload = payloads[0]\n if (isModuleState(payload)) {\n return payload.state\n }\n }\n },\n )\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private poll() {\n this._pollId = setTimeout(async () => {\n try {\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeout(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\n/**\n * Describes an Archivist/Diviner combination\n * that enables searching signed payloads\n */\nexport interface SearchableStorage {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n}\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n /** @deprecated Use appropriate Storage */\n archivist?: string\n /**\n * Where the diviner should store it's index\n */\n indexStore?: SearchableStorage\n /** @deprecated Use appropriate Storage */\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n /**\n * Where the diviner should persist its internal state\n */\n stateStore?: SearchableStorage\n /**\n * Where the diviner should look for stored thumbnails\n */\n thumbnailStore?: SearchableStorage\n}>\n"],"mappings":"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","names":["import_image_thumbnail_payload_plugin","module","_a"]}
@@ -49,15 +49,15 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
49
49
  if (batch.length === 0)
50
50
  return;
51
51
  const imageThumbnailTimestampTuples = batch.filter(isBoundWitness).map((bw) => {
52
- var _a, _b, _c, _d;
53
- const imageThumbnailIndex = (_a = bw.payload_schemas) == null ? void 0 : _a.findIndex((schema) => schema === ImageThumbnailSchema2);
52
+ var _a, _b, _c;
53
+ const imageThumbnailIndexes = (_a = bw.payload_schemas) == null ? void 0 : _a.map((schema, index) => schema === ImageThumbnailSchema2 ? index : void 0).filter(exists);
54
54
  const timestampIndex = (_b = bw.payload_schemas) == null ? void 0 : _b.findIndex((schema) => schema === TimestampSchema);
55
- if (!imageThumbnailIndex || !timestampIndex)
55
+ if (!imageThumbnailIndexes.length || timestampIndex === -1)
56
56
  return void 0;
57
- const imageThumbnail = (_c = bw.payload_hashes) == null ? void 0 : _c[imageThumbnailIndex];
58
- const timestamp = (_d = bw.payload_hashes) == null ? void 0 : _d[timestampIndex];
59
- return [imageThumbnail, timestamp];
60
- }).filter(exists);
57
+ const imageThumbnails = bw.payload_hashes.map((hash, index) => imageThumbnailIndexes.includes(index) ? hash : void 0).filter(exists);
58
+ const timestamp = (_c = bw.payload_hashes) == null ? void 0 : _c[timestampIndex];
59
+ return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp]);
60
+ }).flat().filter(exists);
61
61
  const archivist = await this.getArchivistForStore("thumbnailStore");
62
62
  const payloadTuples = (await Promise.all(
63
63
  imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {
@@ -75,7 +75,7 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
75
75
  )).filter(exists);
76
76
  const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {
77
77
  var _a;
78
- const { url } = thumbnailPayload;
78
+ const { sourceUrl: url } = thumbnailPayload;
79
79
  const { timestamp } = timestampPayload;
80
80
  const status = ((_a = thumbnailPayload.http) == null ? void 0 : _a.status) ?? -1;
81
81
  const sources = [thumbnailHash, timestampHash];
@@ -117,9 +117,9 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
117
117
  }
118
118
  async getArchivistForStore(store, wrap) {
119
119
  var _a, _b;
120
- const name = assertEx((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.archivist not specified`);
120
+ const name = assertEx((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`);
121
121
  const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`);
122
- return wrap ? ArchivistWrapper.wrap(mod, this.account) : asArchivistInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not an Archivist`);
122
+ return wrap ? ArchivistWrapper.wrap(mod, this.account) : asArchivistInstance(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`);
123
123
  }
124
124
  async getBoundWitnessDivinerForStore(store, wrap) {
125
125
  var _a, _b;
@@ -141,12 +141,12 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
141
141
  var _a;
142
142
  let hash = "";
143
143
  const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
144
- const query = new PayloadBuilder({ schema: PayloadDivinerQuerySchema }).fields({
144
+ const query = new PayloadBuilder({ schema: BoundWitnessDivinerQuerySchema }).fields({
145
145
  address: this.account.address,
146
146
  limit: 1,
147
147
  offset: 0,
148
148
  order: "desc",
149
- schemas: [ImageThumbnailSchema2]
149
+ payload_schemas: [ModuleStateSchema]
150
150
  });
151
151
  const boundWitnesses = await diviner.divine([query]);
152
152
  if (boundWitnesses.length > 0) {
@@ -179,6 +179,11 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
179
179
  }
180
180
  return void 0;
181
181
  }
182
+ async startHandler() {
183
+ await super.startHandler();
184
+ this.poll();
185
+ return true;
186
+ }
182
187
  async stopHandler(_timeout) {
183
188
  if (this._pollId) {
184
189
  clearTimeout(this._pollId);
@@ -186,14 +191,19 @@ var ImageThumbnailDiviner = class extends AbstractDiviner {
186
191
  }
187
192
  return await super.stopHandler();
188
193
  }
189
- async poll() {
190
- if (await this.started()) {
191
- this._pollId = setTimeout(async () => {
192
- this._pollId = void 0;
194
+ poll() {
195
+ this._pollId = setTimeout(async () => {
196
+ try {
193
197
  await this.backgroundDivine();
194
- await this.poll();
195
- }, this.pollFrequency);
196
- }
198
+ } catch (e) {
199
+ console.log(e);
200
+ } finally {
201
+ if (this._pollId)
202
+ clearTimeout(this._pollId);
203
+ this._pollId = void 0;
204
+ this.poll();
205
+ }
206
+ }, this.pollFrequency);
197
207
  }
198
208
  };
199
209
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/Diviner/Diviner.ts","../../../src/Diviner/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { asArchivistInstance, withArchivistModule } from '@xyo-network/archivist-model'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance, DivinerConfigSchema } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { ImageThumbnailSchema, isImageThumbnail } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'\nimport { isUrlPayload } from '@xyo-network/url-payload-plugin'\nimport { isTimestamp, TimestampSchema } from '@xyo-network/witness-timestamp'\n\nimport { ImageThumbnailDivinerConfig, ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\n/**\n * TODO: Once the shape settles, make a generic payload so that it\n * can be used for other modules\n */\ninterface State<T> {\n state: T\n}\n\ninterface ImageThumbnailDivinerState {\n offset: number\n}\n\nconst ModuleStateSchema = 'network.xyo.module.state' as const\ntype ModuleStateSchema = typeof ModuleStateSchema\n\ntype ModuleState = Payload<State<ImageThumbnailDivinerState>, ModuleStateSchema>\n\nconst isModuleState = isPayloadOfSchemaType<ModuleState>(ModuleStateSchema)\n\ntype ConfigStoreKey = 'indexStore' | 'stateStore' | 'thumbnailStore'\n\ntype ConfigStore = Extract<keyof ImageThumbnailDivinerConfig, ConfigStoreKey>\n\nconst ImageThumbnailResultIndexSchema = `${ImageThumbnailSchema}.index` as const\ntype ImageThumbnailResultIndexSchema = typeof ImageThumbnailResultIndexSchema\n\ninterface ImageThumbnailResultInfo {\n sources: string[]\n // TODO: Something richer than HTTP status code that allows for info about failure modes\n status: number\n timestamp: number\n url: string\n}\n\ntype ImageThumbnailResult = Payload<ImageThumbnailResultInfo, ImageThumbnailResultIndexSchema>\n\nconst isImageThumbnailResult = isPayloadOfSchemaType<ImageThumbnailResult>(ImageThumbnailResultIndexSchema)\n\n/**\n * The fields that will need to be indexed on in the underlying store\n */\ntype QueryableImageThumbnailResultProperties = Extract<keyof ImageThumbnailResult, 'url' | 'timestamp' | 'status'>\n\n/**\n * The query that will be used to retrieve the results from the underlying store\n */\ntype ImageThumbnailResultQuery = PayloadDivinerQueryPayload & { schemas: [ImageThumbnailSchema] } & Pick<\n ImageThumbnailResult,\n QueryableImageThumbnailResultProperties\n >\n\nconst moduleName = 'ImageThumbnailDiviner'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _pollId?: string | number | NodeJS.Timeout\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1_0000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = (await this.retrieveState()) ?? { offset: 0 }\n const { offset } = lastState\n // Get next batch of results\n const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore('thumbnailStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n limit: this.payloadDivinerLimit,\n offset,\n order: 'asc',\n payload_schemas: [ImageThumbnailSchema, TimestampSchema],\n })\n const batch = await boundWitnessDiviner.divine([query])\n if (batch.length === 0) return\n const imageThumbnailTimestampTuples = batch\n .filter(isBoundWitness)\n .map((bw) => {\n const imageThumbnailIndex = bw.payload_schemas?.findIndex((schema) => schema === ImageThumbnailSchema)\n const timestampIndex = bw.payload_schemas?.findIndex((schema) => schema === TimestampSchema)\n if (!imageThumbnailIndex || !timestampIndex) return undefined\n const imageThumbnail = bw.payload_hashes?.[imageThumbnailIndex]\n const timestamp = bw.payload_hashes?.[timestampIndex]\n return [imageThumbnail, timestamp] as const\n })\n .filter(exists)\n const archivist = await this.getArchivistForStore('thumbnailStore')\n const payloadTuples = (\n await Promise.all(\n imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {\n const results = await archivist.get([imageThumbnailHash, timestampHash])\n const imageThumbnailPayload = results.find(isImageThumbnail)\n const timestampPayload = results.find(isTimestamp)\n if (!imageThumbnailPayload || !timestampPayload) return undefined\n const calculatedImageThumbnailHash = await PayloadHasher.hashAsync(imageThumbnailPayload)\n const calculatedTimestampHash = await PayloadHasher.hashAsync(timestampPayload)\n if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash) return undefined\n return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload] as const\n }),\n )\n ).filter(exists)\n // Build index results\n const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {\n const { url } = thumbnailPayload\n const { timestamp } = timestampPayload\n const status = thumbnailPayload.http?.status ?? -1\n const sources = [thumbnailHash, timestampHash]\n const result = new PayloadBuilder<ImageThumbnailResult>({ schema: ImageThumbnailResultIndexSchema })\n .fields({ sources, status, timestamp, url })\n .build()\n return result\n })\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexedResults)\n // Update state\n const nextOffset = offset + batch.length + 1\n const currentState = { ...lastState, offset: nextOffset }\n await this.commitState(currentState)\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n */\n protected async commitState(state: ImageThumbnailDivinerState) {\n const stateStore = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore configured`)\n const module = assertEx(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`)\n await withArchivistModule(module, async (archivist) => {\n const mod = ArchivistWrapper.wrap(archivist, this.account)\n const payload = new PayloadBuilder<ModuleState>({ schema: ModuleStateSchema }).fields({ state }).build()\n await mod.insert([payload])\n })\n }\n\n protected override async divineHandler(payloads: Payload[] = []): Promise<ImageThumbnailResult[]> {\n const urls = payloads.filter(isUrlPayload).map((urlPayload) => urlPayload.url)\n const diviner = await this.getPayloadDivinerForStore('indexStore')\n const results = (\n await Promise.all(\n urls.map(async (url) => {\n const query = new PayloadBuilder<ImageThumbnailResultQuery>({ schema: PayloadDivinerQuerySchema })\n // TODO: Expose status, limit (and possibly offset) to caller. Currently only exposing URL\n .fields({ limit: 1, offset: 0, order: 'desc', url })\n .build()\n return await diviner.divine([query])\n }),\n )\n )\n .flat()\n .filter(isImageThumbnailResult)\n return results\n }\n\n protected async getArchivistForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`)\n return wrap\n ? ArchivistWrapper.wrap(mod, this.account)\n : asArchivistInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not an Archivist`)\n }\n\n protected async getBoundWitnessDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`)\n return wrap\n ? DivinerWrapper.wrap(mod, this.account)\n : asDivinerInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`)\n }\n\n protected async getPayloadDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`)\n return wrap ? DivinerWrapper.wrap(mod, this.account) : asDivinerInstance(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ImageThumbnailDivinerState | undefined> {\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = new PayloadBuilder<PayloadDivinerQueryPayload>({ schema: PayloadDivinerQuerySchema }).fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n schemas: [ImageThumbnailSchema],\n })\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const stateStoreArchivist = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore archivist configured`)\n await withArchivistModule(\n assertEx(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),\n async (mod) => {\n const archivist = ArchivistWrapper.wrap(mod, this.account)\n const payloads = await archivist.get([hash])\n if (payloads.length > 0) {\n const payload = payloads[0]\n if (isModuleState(payload)) {\n return payload.state\n }\n }\n },\n )\n }\n return undefined\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private async poll() {\n if (await this.started()) {\n this._pollId = setTimeout(async () => {\n this._pollId = undefined\n await this.backgroundDivine()\n await this.poll()\n }, this.pollFrequency)\n }\n }\n}\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\n/**\n * Describes an Archivist/Diviner combination\n * that enables searching signed payloads\n */\nexport interface SearchableStorage {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n}\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n /** @deprecated Use appropriate Storage */\n archivist?: string\n /**\n * Where the diviner should store it's index\n */\n indexStore?: SearchableStorage\n /** @deprecated Use appropriate Storage */\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n /**\n * Where the diviner should persist its internal state\n */\n stateStore?: SearchableStorage\n /**\n * Where the diviner should look for stored thumbnails\n */\n thumbnailStore?: SearchableStorage\n}>\n"],"mappings":"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","names":["ImageThumbnailSchema","ImageThumbnailSchema","_a"]}
1
+ {"version":3,"sources":["../../../src/Diviner/Diviner.ts","../../../src/Diviner/Config.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { exists } from '@xylabs/exists'\nimport { AbstractDiviner } from '@xyo-network/abstract-diviner'\nimport { asArchivistInstance, withArchivistModule } from '@xyo-network/archivist-model'\nimport { ArchivistWrapper } from '@xyo-network/archivist-wrapper'\nimport { isBoundWitness } from '@xyo-network/boundwitness-model'\nimport { PayloadHasher } from '@xyo-network/core'\nimport { BoundWitnessDivinerQueryPayload, BoundWitnessDivinerQuerySchema } from '@xyo-network/diviner-boundwitness-model'\nimport { asDivinerInstance, DivinerConfigSchema } from '@xyo-network/diviner-model'\nimport { PayloadDivinerQueryPayload, PayloadDivinerQuerySchema } from '@xyo-network/diviner-payload-model'\nimport { DivinerWrapper } from '@xyo-network/diviner-wrapper'\nimport { ImageThumbnailSchema, isImageThumbnail } from '@xyo-network/image-thumbnail-payload-plugin'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { isPayloadOfSchemaType, Payload } from '@xyo-network/payload-model'\nimport { isUrlPayload } from '@xyo-network/url-payload-plugin'\nimport { isTimestamp, TimestampSchema } from '@xyo-network/witness-timestamp'\n\nimport { ImageThumbnailDivinerConfig, ImageThumbnailDivinerConfigSchema } from './Config'\nimport { ImageThumbnailDivinerParams } from './Params'\n\n/**\n * TODO: Once the shape settles, make a generic payload so that it\n * can be used for other modules\n */\ninterface State<T> {\n state: T\n}\n\ninterface ImageThumbnailDivinerState {\n offset: number\n}\n\nconst ModuleStateSchema = 'network.xyo.module.state' as const\ntype ModuleStateSchema = typeof ModuleStateSchema\n\ntype ModuleState = Payload<State<ImageThumbnailDivinerState>, ModuleStateSchema>\n\nconst isModuleState = isPayloadOfSchemaType<ModuleState>(ModuleStateSchema)\n\ntype ConfigStoreKey = 'indexStore' | 'stateStore' | 'thumbnailStore'\n\ntype ConfigStore = Extract<keyof ImageThumbnailDivinerConfig, ConfigStoreKey>\n\nconst ImageThumbnailResultIndexSchema = `${ImageThumbnailSchema}.index` as const\ntype ImageThumbnailResultIndexSchema = typeof ImageThumbnailResultIndexSchema\n\ninterface ImageThumbnailResultInfo {\n sources: string[]\n // TODO: Something richer than HTTP status code that allows for info about failure modes\n status: number\n timestamp: number\n url: string\n}\n\ntype ImageThumbnailResult = Payload<ImageThumbnailResultInfo, ImageThumbnailResultIndexSchema>\n\nconst isImageThumbnailResult = isPayloadOfSchemaType<ImageThumbnailResult>(ImageThumbnailResultIndexSchema)\n\n/**\n * The fields that will need to be indexed on in the underlying store\n */\ntype QueryableImageThumbnailResultProperties = Extract<keyof ImageThumbnailResult, 'url' | 'timestamp' | 'status'>\n\n/**\n * The query that will be used to retrieve the results from the underlying store\n */\ntype ImageThumbnailResultQuery = PayloadDivinerQueryPayload & { schemas: [ImageThumbnailSchema] } & Pick<\n ImageThumbnailResult,\n QueryableImageThumbnailResultProperties\n >\n\nconst moduleName = 'ImageThumbnailDiviner'\n\nexport class ImageThumbnailDiviner<TParams extends ImageThumbnailDivinerParams = ImageThumbnailDivinerParams> extends AbstractDiviner<TParams> {\n static override configSchemas = [ImageThumbnailDivinerConfigSchema, DivinerConfigSchema]\n\n private _pollId?: string | number | NodeJS.Timeout\n\n get payloadDivinerLimit() {\n return this.config.payloadDivinerLimit ?? 1_0000\n }\n\n get pollFrequency() {\n return this.config.pollFrequency ?? 10_000\n }\n\n protected backgroundDivine = async (): Promise<void> => {\n // Load last state\n const lastState = (await this.retrieveState()) ?? { offset: 0 }\n const { offset } = lastState\n // Get next batch of results\n const boundWitnessDiviner = await this.getBoundWitnessDivinerForStore('thumbnailStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n limit: this.payloadDivinerLimit,\n offset,\n order: 'asc',\n payload_schemas: [ImageThumbnailSchema, TimestampSchema],\n })\n const batch = await boundWitnessDiviner.divine([query])\n if (batch.length === 0) return\n const imageThumbnailTimestampTuples = batch\n .filter(isBoundWitness)\n .map((bw) => {\n const imageThumbnailIndexes = bw.payload_schemas?.map((schema, index) => (schema === ImageThumbnailSchema ? index : undefined)).filter(exists)\n const timestampIndex = bw.payload_schemas?.findIndex((schema) => schema === TimestampSchema)\n if (!imageThumbnailIndexes.length || timestampIndex === -1) return undefined\n const imageThumbnails = bw.payload_hashes.map((hash, index) => (imageThumbnailIndexes.includes(index) ? hash : undefined)).filter(exists)\n const timestamp = bw.payload_hashes?.[timestampIndex]\n return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp] as const)\n })\n .flat()\n .filter(exists)\n const archivist = await this.getArchivistForStore('thumbnailStore')\n const payloadTuples = (\n await Promise.all(\n imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {\n const results = await archivist.get([imageThumbnailHash, timestampHash])\n const imageThumbnailPayload = results.find(isImageThumbnail)\n const timestampPayload = results.find(isTimestamp)\n if (!imageThumbnailPayload || !timestampPayload) return undefined\n const calculatedImageThumbnailHash = await PayloadHasher.hashAsync(imageThumbnailPayload)\n const calculatedTimestampHash = await PayloadHasher.hashAsync(timestampPayload)\n if (imageThumbnailHash !== calculatedImageThumbnailHash || timestampHash !== calculatedTimestampHash) return undefined\n return [imageThumbnailHash, imageThumbnailPayload, timestampHash, timestampPayload] as const\n }),\n )\n ).filter(exists)\n // Build index results\n const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {\n const { sourceUrl: url } = thumbnailPayload\n const { timestamp } = timestampPayload\n const status = thumbnailPayload.http?.status ?? -1\n const sources = [thumbnailHash, timestampHash]\n const result = new PayloadBuilder<ImageThumbnailResult>({ schema: ImageThumbnailResultIndexSchema })\n .fields({ sources, status, timestamp, url })\n .build()\n return result\n })\n // Insert index results\n const indexArchivist = await this.getArchivistForStore('indexStore')\n await indexArchivist.insert(indexedResults)\n // Update state\n const nextOffset = offset + batch.length + 1\n const currentState = { ...lastState, offset: nextOffset }\n await this.commitState(currentState)\n }\n\n /**\n * Commit the internal state of the Diviner process. This is similar\n * to a transaction completion in a database and should only be called\n * when results have been successfully persisted to the appropriate\n * external stores.\n */\n protected async commitState(state: ImageThumbnailDivinerState) {\n const stateStore = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore configured`)\n const module = assertEx(await this.resolve(stateStore), `${moduleName}: Failed to resolve stateStore`)\n await withArchivistModule(module, async (archivist) => {\n const mod = ArchivistWrapper.wrap(archivist, this.account)\n const payload = new PayloadBuilder<ModuleState>({ schema: ModuleStateSchema }).fields({ state }).build()\n await mod.insert([payload])\n })\n }\n\n protected override async divineHandler(payloads: Payload[] = []): Promise<ImageThumbnailResult[]> {\n const urls = payloads.filter(isUrlPayload).map((urlPayload) => urlPayload.url)\n const diviner = await this.getPayloadDivinerForStore('indexStore')\n const results = (\n await Promise.all(\n urls.map(async (url) => {\n const query = new PayloadBuilder<ImageThumbnailResultQuery>({ schema: PayloadDivinerQuerySchema })\n // TODO: Expose status, limit (and possibly offset) to caller. Currently only exposing URL\n .fields({ limit: 1, offset: 0, order: 'desc', url })\n .build()\n return await diviner.divine([query])\n }),\n )\n )\n .flat()\n .filter(isImageThumbnailResult)\n return results\n }\n\n protected async getArchivistForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`)\n return wrap ? ArchivistWrapper.wrap(mod, this.account) : asArchivistInstance(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`)\n }\n\n protected async getBoundWitnessDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.boundWitnessDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.boundWitnessDiviner`)\n return wrap\n ? DivinerWrapper.wrap(mod, this.account)\n : asDivinerInstance(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not a Diviner`)\n }\n\n protected async getPayloadDivinerForStore(store: ConfigStore, wrap?: boolean) {\n const name = assertEx(this.config?.[store]?.payloadDiviner, () => `${moduleName}: Config for ${store}.payloadDiviner not specified`)\n const mod = assertEx(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.payloadDiviner`)\n return wrap ? DivinerWrapper.wrap(mod, this.account) : asDivinerInstance(mod, () => `${moduleName}: ${store}.payloadDiviner is not a Diviner`)\n }\n\n /**\n * Retrieves the last state of the Diviner process. Used to recover state after\n * preemptions, reboots, etc.\n */\n protected async retrieveState(): Promise<ImageThumbnailDivinerState | undefined> {\n let hash: string = ''\n const diviner = await this.getBoundWitnessDivinerForStore('stateStore')\n const query = new PayloadBuilder<BoundWitnessDivinerQueryPayload>({ schema: BoundWitnessDivinerQuerySchema }).fields({\n address: this.account.address,\n limit: 1,\n offset: 0,\n order: 'desc',\n payload_schemas: [ModuleStateSchema],\n })\n const boundWitnesses = await diviner.divine([query])\n if (boundWitnesses.length > 0) {\n const boundWitness = boundWitnesses[0]\n if (isBoundWitness(boundWitness)) {\n // Find the index for this address in the BoundWitness that is a ModuleState\n hash = boundWitness.addresses\n .map((address, index) => ({ address, index }))\n .filter(({ address }) => address === this.account.address)\n .reduce(\n (prev, curr) => (boundWitness.payload_schemas?.[curr?.index] === ModuleStateSchema ? boundWitness.payload_hashes[curr?.index] : prev),\n '',\n )\n }\n }\n\n // If we able to located the last state\n if (hash) {\n // Get last state\n const stateStoreArchivist = assertEx(this.config.stateStore?.archivist, `${moduleName}: No stateStore archivist configured`)\n await withArchivistModule(\n assertEx(await this.resolve(stateStoreArchivist), `${moduleName}: Failed to resolve stateStore archivist`),\n async (mod) => {\n const archivist = ArchivistWrapper.wrap(mod, this.account)\n const payloads = await archivist.get([hash])\n if (payloads.length > 0) {\n const payload = payloads[0]\n if (isModuleState(payload)) {\n return payload.state\n }\n }\n },\n )\n }\n return undefined\n }\n\n protected override async startHandler(): Promise<boolean> {\n await super.startHandler()\n this.poll()\n return true\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n if (this._pollId) {\n clearTimeout(this._pollId)\n this._pollId = undefined\n }\n return await super.stopHandler()\n }\n\n private poll() {\n this._pollId = setTimeout(async () => {\n try {\n await this.backgroundDivine()\n } catch (e) {\n console.log(e)\n } finally {\n if (this._pollId) clearTimeout(this._pollId)\n this._pollId = undefined\n this.poll()\n }\n }, this.pollFrequency)\n }\n}\n","import { DivinerConfig } from '@xyo-network/diviner-model'\nimport { ImageThumbnailSchema } from '@xyo-network/image-thumbnail-payload-plugin'\n\nexport const ImageThumbnailDivinerConfigSchema = `${ImageThumbnailSchema}.diviner.config` as const\nexport type ImageThumbnailDivinerConfigSchema = typeof ImageThumbnailDivinerConfigSchema\n\n/**\n * Describes an Archivist/Diviner combination\n * that enables searching signed payloads\n */\nexport interface SearchableStorage {\n archivist: string\n boundWitnessDiviner: string\n payloadDiviner: string\n}\n\nexport type ImageThumbnailDivinerConfig = DivinerConfig<{\n /** @deprecated Use appropriate Storage */\n archivist?: string\n /**\n * Where the diviner should store it's index\n */\n indexStore?: SearchableStorage\n /** @deprecated Use appropriate Storage */\n payloadDiviner?: string\n payloadDivinerLimit?: number\n pollFrequency?: number\n schema: ImageThumbnailDivinerConfigSchema\n /**\n * Where the diviner should persist its internal state\n */\n stateStore?: SearchableStorage\n /**\n * Where the diviner should look for stored thumbnails\n */\n thumbnailStore?: SearchableStorage\n}>\n"],"mappings":"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","names":["ImageThumbnailSchema","ImageThumbnailSchema","_a"]}
@@ -74,15 +74,15 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
74
74
  if (batch.length === 0)
75
75
  return;
76
76
  const imageThumbnailTimestampTuples = batch.filter(import_boundwitness_model.isBoundWitness).map((bw) => {
77
- var _a, _b, _c, _d;
78
- const imageThumbnailIndex = (_a = bw.payload_schemas) == null ? void 0 : _a.findIndex((schema) => schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema);
77
+ var _a, _b, _c;
78
+ const imageThumbnailIndexes = (_a = bw.payload_schemas) == null ? void 0 : _a.map((schema, index) => schema === import_image_thumbnail_payload_plugin2.ImageThumbnailSchema ? index : void 0).filter(import_exists.exists);
79
79
  const timestampIndex = (_b = bw.payload_schemas) == null ? void 0 : _b.findIndex((schema) => schema === import_witness_timestamp.TimestampSchema);
80
- if (!imageThumbnailIndex || !timestampIndex)
80
+ if (!imageThumbnailIndexes.length || timestampIndex === -1)
81
81
  return void 0;
82
- const imageThumbnail = (_c = bw.payload_hashes) == null ? void 0 : _c[imageThumbnailIndex];
83
- const timestamp = (_d = bw.payload_hashes) == null ? void 0 : _d[timestampIndex];
84
- return [imageThumbnail, timestamp];
85
- }).filter(import_exists.exists);
82
+ const imageThumbnails = bw.payload_hashes.map((hash, index) => imageThumbnailIndexes.includes(index) ? hash : void 0).filter(import_exists.exists);
83
+ const timestamp = (_c = bw.payload_hashes) == null ? void 0 : _c[timestampIndex];
84
+ return imageThumbnails.map((imageThumbnail) => [imageThumbnail, timestamp]);
85
+ }).flat().filter(import_exists.exists);
86
86
  const archivist = await this.getArchivistForStore("thumbnailStore");
87
87
  const payloadTuples = (await Promise.all(
88
88
  imageThumbnailTimestampTuples.map(async ([imageThumbnailHash, timestampHash]) => {
@@ -100,7 +100,7 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
100
100
  )).filter(import_exists.exists);
101
101
  const indexedResults = payloadTuples.map(([thumbnailHash, thumbnailPayload, timestampHash, timestampPayload]) => {
102
102
  var _a;
103
- const { url } = thumbnailPayload;
103
+ const { sourceUrl: url } = thumbnailPayload;
104
104
  const { timestamp } = timestampPayload;
105
105
  const status = ((_a = thumbnailPayload.http) == null ? void 0 : _a.status) ?? -1;
106
106
  const sources = [thumbnailHash, timestampHash];
@@ -142,9 +142,9 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
142
142
  }
143
143
  async getArchivistForStore(store, wrap) {
144
144
  var _a, _b;
145
- const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.boundWitnessDiviner, () => `${moduleName}: Config for ${store}.archivist not specified`);
145
+ const name = (0, import_assert.assertEx)((_b = (_a = this.config) == null ? void 0 : _a[store]) == null ? void 0 : _b.archivist, () => `${moduleName}: Config for ${store}.archivist not specified`);
146
146
  const mod = (0, import_assert.assertEx)(await this.resolve(name), () => `${moduleName}: Failed to resolve ${store}.archivist`);
147
- return wrap ? import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account) : (0, import_archivist_model.asArchivistInstance)(mod, () => `${moduleName}: ${store}.boundWitnessDiviner is not an Archivist`);
147
+ return wrap ? import_archivist_wrapper.ArchivistWrapper.wrap(mod, this.account) : (0, import_archivist_model.asArchivistInstance)(mod, () => `${moduleName}: ${store}.archivist is not an Archivist`);
148
148
  }
149
149
  async getBoundWitnessDivinerForStore(store, wrap) {
150
150
  var _a, _b;
@@ -166,12 +166,12 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
166
166
  var _a;
167
167
  let hash = "";
168
168
  const diviner = await this.getBoundWitnessDivinerForStore("stateStore");
169
- const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_payload_model.PayloadDivinerQuerySchema }).fields({
169
+ const query = new import_payload_builder.PayloadBuilder({ schema: import_diviner_boundwitness_model.BoundWitnessDivinerQuerySchema }).fields({
170
170
  address: this.account.address,
171
171
  limit: 1,
172
172
  offset: 0,
173
173
  order: "desc",
174
- schemas: [import_image_thumbnail_payload_plugin2.ImageThumbnailSchema]
174
+ payload_schemas: [ModuleStateSchema]
175
175
  });
176
176
  const boundWitnesses = await diviner.divine([query]);
177
177
  if (boundWitnesses.length > 0) {
@@ -204,6 +204,11 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
204
204
  }
205
205
  return void 0;
206
206
  }
207
+ async startHandler() {
208
+ await super.startHandler();
209
+ this.poll();
210
+ return true;
211
+ }
207
212
  async stopHandler(_timeout) {
208
213
  if (this._pollId) {
209
214
  clearTimeout(this._pollId);
@@ -211,14 +216,19 @@ var ImageThumbnailDiviner = class extends import_abstract_diviner.AbstractDivine
211
216
  }
212
217
  return await super.stopHandler();
213
218
  }
214
- async poll() {
215
- if (await this.started()) {
216
- this._pollId = setTimeout(async () => {
217
- this._pollId = void 0;
219
+ poll() {
220
+ this._pollId = setTimeout(async () => {
221
+ try {
218
222
  await this.backgroundDivine();
219
- await this.poll();
220
- }, this.pollFrequency);
221
- }
223
+ } catch (e) {
224
+ console.log(e);
225
+ } finally {
226
+ if (this._pollId)
227
+ clearTimeout(this._pollId);
228
+ this._pollId = void 0;
229
+ this.poll();
230
+ }
231
+ }, this.pollFrequency);
222
232
  }
223
233
  };
224
234
  // Annotate the CommonJS export names for ESM import in node: