@graffiti-garden/implementation-decentralized 0.0.3 → 0.0.4

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.
@@ -105,6 +105,7 @@ const MESSAGE_LABEL_UNLABELED = 0;
105
105
  const MESSAGE_LABEL_VALID = 1;
106
106
  const MESSAGE_LABEL_TRASH = 2;
107
107
  const MESSAGE_LABEL_INVALID = 3;
108
+ const CONCURRENCY = 16;
108
109
  class GraffitiDecentralized {
109
110
  dids = new DecentralizedIdentifiers();
110
111
  authorization = new Authorization();
@@ -615,14 +616,14 @@ class GraffitiDecentralized {
615
616
  cursor: JSON.stringify({
616
617
  channels,
617
618
  cursors
618
- }),
619
- continue: (session2) => this.discoverMeta(channels, schema, cursors, session2)
619
+ })
620
620
  };
621
621
  }
622
622
  discover = (...args) => {
623
623
  const [channels, schema, session] = args;
624
624
  return this.discoverMeta(channels, schema, {}, session);
625
625
  };
626
+ // @ts-ignore
626
627
  continueDiscover = (...args) => {
627
628
  const [cursor, session] = args;
628
629
  let channels;
@@ -769,62 +770,160 @@ class GraffitiDecentralized {
769
770
  queryArguments.cursor,
770
771
  inboxToken
771
772
  );
773
+ const inFlight = [];
774
+ let doneValue = null;
772
775
  while (true) {
773
- const itResult = await iterator.next();
774
- if (itResult.done) return itResult.value;
775
- const result = itResult.value;
776
- const label = result.l;
777
- if (label !== MESSAGE_LABEL_VALID && label !== MESSAGE_LABEL_UNLABELED && label !== MESSAGE_LABEL_TRASH)
778
- continue;
779
- const messageId = result.id;
780
- const { o: object, m: metadataBytes, t: receivedTags } = result.m;
781
- let metadata;
782
- try {
783
- const metadataRaw = dagCborDecode(metadataBytes);
784
- metadata = MessageMetadataSchema.parse(metadataRaw);
785
- } catch (e) {
786
- this.inboxes.label(
776
+ while (doneValue === null && inFlight.length < CONCURRENCY) {
777
+ const itResult = await iterator.next();
778
+ if (itResult.done) {
779
+ doneValue = itResult.value;
780
+ break;
781
+ }
782
+ const processPromise = this.processOneLabeledMessage(
787
783
  inboxEndpoint,
788
- messageId,
789
- MESSAGE_LABEL_INVALID,
790
- inboxToken
791
- );
792
- continue;
784
+ itResult.value,
785
+ inboxToken,
786
+ recipient
787
+ ).catch((e) => {
788
+ throw e;
789
+ });
790
+ inFlight.push(processPromise);
793
791
  }
794
- const {
795
- [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,
796
- [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId
797
- } = metadata;
798
- const allowedTickets = MESSAGE_DATA_ALLOWED_TICKETS_KEY in metadata ? metadata[MESSAGE_DATA_ALLOWED_TICKETS_KEY] : void 0;
799
- const announcements = MESSAGE_DATA_ANNOUNCEMENTS_KEY in metadata ? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY] : void 0;
800
- if (label === MESSAGE_LABEL_VALID) {
801
- yield {
802
- messageId,
803
- object,
804
- storageBucketKey,
805
- allowedTickets,
806
- tags: receivedTags,
807
- announcements
808
- };
809
- continue;
810
- } else if (label === MESSAGE_LABEL_TRASH) {
811
- if (!tombstonedMessageId) continue;
812
- const past = await this.inboxes.get(
792
+ const nextProcessedPromise = inFlight.shift();
793
+ if (!nextProcessedPromise) {
794
+ if (doneValue !== null) return doneValue;
795
+ throw new Error("Process queue empty but no return value");
796
+ }
797
+ const processed = await nextProcessedPromise;
798
+ if (processed) yield processed;
799
+ }
800
+ }
801
+ async processOneLabeledMessage(inboxEndpoint, result, inboxToken, recipient) {
802
+ const label = result.l;
803
+ if (label !== MESSAGE_LABEL_VALID && label !== MESSAGE_LABEL_UNLABELED && label !== MESSAGE_LABEL_TRASH)
804
+ return;
805
+ const messageId = result.id;
806
+ const { o: object, m: metadataBytes, t: receivedTags } = result.m;
807
+ let metadata;
808
+ try {
809
+ const metadataRaw = dagCborDecode(metadataBytes);
810
+ metadata = MessageMetadataSchema.parse(metadataRaw);
811
+ } catch (e) {
812
+ this.inboxes.label(
813
+ inboxEndpoint,
814
+ messageId,
815
+ MESSAGE_LABEL_INVALID,
816
+ inboxToken
817
+ );
818
+ return;
819
+ }
820
+ const {
821
+ [MESSAGE_DATA_STORAGE_BUCKET_KEY]: storageBucketKey,
822
+ [MESSAGE_DATA_TOMBSTONED_MESSAGE_ID_KEY]: tombstonedMessageId
823
+ } = metadata;
824
+ const allowedTickets = MESSAGE_DATA_ALLOWED_TICKETS_KEY in metadata ? metadata[MESSAGE_DATA_ALLOWED_TICKETS_KEY] : void 0;
825
+ const announcements = MESSAGE_DATA_ANNOUNCEMENTS_KEY in metadata ? metadata[MESSAGE_DATA_ANNOUNCEMENTS_KEY] : void 0;
826
+ if (label === MESSAGE_LABEL_VALID) {
827
+ return {
828
+ messageId,
829
+ object,
830
+ storageBucketKey,
831
+ allowedTickets,
832
+ tags: receivedTags,
833
+ announcements
834
+ };
835
+ } else if (label === MESSAGE_LABEL_TRASH) {
836
+ if (!tombstonedMessageId) return;
837
+ const past = await this.inboxes.get(
838
+ inboxEndpoint,
839
+ tombstonedMessageId,
840
+ inboxToken
841
+ );
842
+ if (!past || past[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url !== object.url)
843
+ return;
844
+ if (past[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH) {
845
+ this.inboxes.label(
813
846
  inboxEndpoint,
814
847
  tombstonedMessageId,
848
+ MESSAGE_LABEL_TRASH,
815
849
  inboxToken
816
850
  );
817
- if (!past || past[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url !== object.url)
818
- continue;
819
- if (past[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH) {
851
+ }
852
+ return {
853
+ messageId,
854
+ tombstone: true,
855
+ object,
856
+ storageBucketKey,
857
+ allowedTickets,
858
+ tags: receivedTags,
859
+ announcements
860
+ };
861
+ }
862
+ let validationError = void 0;
863
+ try {
864
+ const actor = object.actor;
865
+ const actorDocument = await this.dids.resolve(actor);
866
+ const storageBucketService = actorDocument?.service?.find(
867
+ (service) => service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET && service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET
868
+ );
869
+ if (!storageBucketService) {
870
+ throw new GraffitiErrorNotFound(
871
+ `Actor ${actor} has no storage bucket service`
872
+ );
873
+ }
874
+ if (typeof storageBucketService.serviceEndpoint !== "string") {
875
+ throw new GraffitiErrorNotFound(
876
+ `Actor ${actor} does not have a valid storage bucket endpoint`
877
+ );
878
+ }
879
+ const storageBucketEndpoint = storageBucketService.serviceEndpoint;
880
+ const objectBytes = await this.storageBuckets.get(
881
+ storageBucketEndpoint,
882
+ storageBucketKey,
883
+ MAX_OBJECT_SIZE_BYTES
884
+ );
885
+ if (MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata && !recipient) {
886
+ throw new GraffitiErrorForbidden(
887
+ `Recipient is required when allowed ticket is present`
888
+ );
889
+ }
890
+ const privateObjectInfo = allowedTickets ? { allowedTickets } : MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata ? {
891
+ recipient: recipient ?? "null",
892
+ allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],
893
+ allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]
894
+ } : void 0;
895
+ await this.objectEncoding.validate(
896
+ object,
897
+ receivedTags,
898
+ objectBytes,
899
+ privateObjectInfo
900
+ );
901
+ } catch (e) {
902
+ validationError = e;
903
+ }
904
+ if (tombstonedMessageId) {
905
+ if (validationError instanceof GraffitiErrorNotFound) {
906
+ this.inboxes.get(inboxEndpoint, tombstonedMessageId, inboxToken).then((result2) => {
907
+ if (
908
+ // Make sure that it actually references the object being deleted
909
+ result2 && result2[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url === object.url && // And that the object is not already marked as trash
910
+ result2[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH
911
+ ) {
912
+ this.inboxes.label(
913
+ inboxEndpoint,
914
+ tombstonedMessageId,
915
+ MESSAGE_LABEL_TRASH,
916
+ inboxToken
917
+ );
918
+ }
820
919
  this.inboxes.label(
821
920
  inboxEndpoint,
822
- tombstonedMessageId,
921
+ messageId,
823
922
  MESSAGE_LABEL_TRASH,
824
923
  inboxToken
825
924
  );
826
- }
827
- yield {
925
+ });
926
+ return {
828
927
  messageId,
829
928
  tombstone: true,
830
929
  object,
@@ -833,117 +932,48 @@ class GraffitiDecentralized {
833
932
  tags: receivedTags,
834
933
  announcements
835
934
  };
836
- continue;
837
- }
838
- let validationError = void 0;
839
- try {
840
- const actor = object.actor;
841
- const actorDocument = await this.dids.resolve(actor);
842
- const storageBucketService = actorDocument?.service?.find(
843
- (service) => service.id === DID_SERVICE_ID_GRAFFITI_STORAGE_BUCKET && service.type === DID_SERVICE_TYPE_GRAFFITI_STORAGE_BUCKET
935
+ } else {
936
+ console.error("Recieved an incorrect tombstone object");
937
+ console.error(validationError);
938
+ this.inboxes.label(
939
+ inboxEndpoint,
940
+ messageId,
941
+ MESSAGE_LABEL_INVALID,
942
+ inboxToken
844
943
  );
845
- if (!storageBucketService) {
846
- throw new GraffitiErrorNotFound(
847
- `Actor ${actor} has no storage bucket service`
848
- );
849
- }
850
- if (typeof storageBucketService.serviceEndpoint !== "string") {
851
- throw new GraffitiErrorNotFound(
852
- `Actor ${actor} does not have a valid storage bucket endpoint`
853
- );
854
- }
855
- const storageBucketEndpoint = storageBucketService.serviceEndpoint;
856
- const objectBytes = await this.storageBuckets.get(
857
- storageBucketEndpoint,
858
- storageBucketKey,
859
- MAX_OBJECT_SIZE_BYTES
944
+ }
945
+ } else {
946
+ if (validationError === void 0) {
947
+ this.inboxes.label(
948
+ inboxEndpoint,
949
+ messageId,
950
+ MESSAGE_LABEL_VALID,
951
+ inboxToken
860
952
  );
861
- if (MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata && !recipient) {
862
- throw new GraffitiErrorForbidden(
863
- `Recipient is required when allowed ticket is present`
864
- );
865
- }
866
- const privateObjectInfo = allowedTickets ? { allowedTickets } : MESSAGE_DATA_ALLOWED_TICKET_KEY in metadata ? {
867
- recipient: recipient ?? "null",
868
- allowedTicket: metadata[MESSAGE_DATA_ALLOWED_TICKET_KEY],
869
- allowedIndex: metadata[MESSAGE_DATA_ALLOWED_TICKET_INDEX_KEY]
870
- } : void 0;
871
- await this.objectEncoding.validate(
953
+ return {
954
+ messageId,
872
955
  object,
873
- receivedTags,
874
- objectBytes,
875
- privateObjectInfo
956
+ storageBucketKey,
957
+ tags: receivedTags,
958
+ allowedTickets,
959
+ announcements
960
+ };
961
+ } else if (validationError instanceof GraffitiErrorNotFound) {
962
+ this.inboxes.label(
963
+ inboxEndpoint,
964
+ messageId,
965
+ MESSAGE_LABEL_TRASH,
966
+ inboxToken
876
967
  );
877
- } catch (e) {
878
- validationError = e;
879
- }
880
- if (tombstonedMessageId) {
881
- if (validationError instanceof GraffitiErrorNotFound) {
882
- this.inboxes.get(inboxEndpoint, tombstonedMessageId, inboxToken).then((result2) => {
883
- if (
884
- // Make sure that it actually references the object being deleted
885
- result2 && result2[LABELED_MESSAGE_MESSAGE_KEY][MESSAGE_OBJECT_KEY].url === object.url && // And that the object is not already marked as trash
886
- result2[LABELED_MESSAGE_LABEL_KEY] !== MESSAGE_LABEL_TRASH
887
- ) {
888
- this.inboxes.label(
889
- inboxEndpoint,
890
- tombstonedMessageId,
891
- MESSAGE_LABEL_TRASH,
892
- inboxToken
893
- );
894
- }
895
- this.inboxes.label(
896
- inboxEndpoint,
897
- messageId,
898
- MESSAGE_LABEL_TRASH,
899
- inboxToken
900
- );
901
- });
902
- yield {
903
- messageId,
904
- tombstone: true,
905
- object,
906
- storageBucketKey,
907
- allowedTickets,
908
- tags: receivedTags,
909
- announcements
910
- };
911
- } else {
912
- console.error("Recieved an incorrect object");
913
- console.error(validationError);
914
- this.inboxes.label(
915
- inboxEndpoint,
916
- messageId,
917
- MESSAGE_LABEL_INVALID,
918
- inboxToken
919
- );
920
- }
921
968
  } else {
922
- if (validationError === void 0) {
923
- this.inboxes.label(
924
- inboxEndpoint,
925
- messageId,
926
- MESSAGE_LABEL_VALID,
927
- inboxToken
928
- );
929
- yield {
930
- messageId,
931
- object,
932
- storageBucketKey,
933
- tags: receivedTags,
934
- allowedTickets,
935
- announcements
936
- };
937
- } else {
938
- console.error("Recieved an incorrect object");
939
- console.error(validationError);
940
- this.inboxes.label(
941
- inboxEndpoint,
942
- messageId,
943
- MESSAGE_LABEL_INVALID,
944
- inboxToken
945
- );
946
- }
969
+ console.error("Recieved an incorrect object");
970
+ console.error(validationError);
971
+ this.inboxes.label(
972
+ inboxEndpoint,
973
+ messageId,
974
+ MESSAGE_LABEL_INVALID,
975
+ inboxToken
976
+ );
947
977
  }
948
978
  }
949
979
  }