@dxos/echo-db 2.33.5-dev.b7c9d504 → 2.33.5-dev.bbe0c471

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.
Files changed (184) hide show
  1. package/dist/src/api/selection/queries.d.ts.map +1 -1
  2. package/dist/src/api/selection/queries.js +13 -17
  3. package/dist/src/api/selection/queries.js.map +1 -1
  4. package/dist/src/api/selection/selection.d.ts.map +1 -1
  5. package/dist/src/api/selection/selection.js +1 -3
  6. package/dist/src/api/selection/selection.js.map +1 -1
  7. package/dist/src/api/selection/selection.test.js +4 -12
  8. package/dist/src/api/selection/selection.test.js.map +1 -1
  9. package/dist/src/database/item-demuxer.d.ts +1 -1
  10. package/dist/src/database/item-demuxer.d.ts.map +1 -1
  11. package/dist/src/database/item-demuxer.js +3 -5
  12. package/dist/src/database/item-demuxer.js.map +1 -1
  13. package/dist/src/database/item-manager.js +2 -2
  14. package/dist/src/database/item-manager.js.map +1 -1
  15. package/dist/src/database/testing.js +1 -1
  16. package/dist/src/database/testing.js.map +1 -1
  17. package/dist/src/echo.d.ts +1 -0
  18. package/dist/src/echo.d.ts.map +1 -1
  19. package/dist/src/echo.js +7 -18
  20. package/dist/src/echo.js.map +1 -1
  21. package/dist/src/halo/halo-factory.d.ts.map +1 -1
  22. package/dist/src/halo/halo-factory.js +5 -11
  23. package/dist/src/halo/halo-factory.js.map +1 -1
  24. package/dist/src/halo/halo-party.d.ts +1 -1
  25. package/dist/src/halo/halo-party.d.ts.map +1 -1
  26. package/dist/src/halo/halo-party.js +8 -6
  27. package/dist/src/halo/halo-party.js.map +1 -1
  28. package/dist/src/halo/halo.test.js +4 -3
  29. package/dist/src/halo/halo.test.js.map +1 -1
  30. package/dist/src/halo/identity.js +2 -2
  31. package/dist/src/halo/identity.js.map +1 -1
  32. package/dist/src/halo/party-opener.d.ts +1 -1
  33. package/dist/src/halo/party-opener.d.ts.map +1 -1
  34. package/dist/src/halo/party-opener.js +2 -2
  35. package/dist/src/halo/party-opener.js.map +1 -1
  36. package/dist/src/halo/preferences.d.ts.map +1 -1
  37. package/dist/src/halo/preferences.js +7 -10
  38. package/dist/src/halo/preferences.js.map +1 -1
  39. package/dist/src/invitations/greeting-protocol-provider.d.ts.map +1 -1
  40. package/dist/src/invitations/greeting-protocol-provider.js +5 -9
  41. package/dist/src/invitations/greeting-protocol-provider.js.map +1 -1
  42. package/dist/src/invitations/greeting-responder.d.ts +6 -4
  43. package/dist/src/invitations/greeting-responder.d.ts.map +1 -1
  44. package/dist/src/invitations/greeting-responder.js +11 -14
  45. package/dist/src/invitations/greeting-responder.js.map +1 -1
  46. package/dist/src/invitations/invitation-factory.d.ts +5 -2
  47. package/dist/src/invitations/invitation-factory.d.ts.map +1 -1
  48. package/dist/src/invitations/invitation-factory.js +4 -3
  49. package/dist/src/invitations/invitation-factory.js.map +1 -1
  50. package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
  51. package/dist/src/invitations/offline-invitation-claimer.js +5 -7
  52. package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
  53. package/dist/src/parties/data-party.d.ts +5 -3
  54. package/dist/src/parties/data-party.d.ts.map +1 -1
  55. package/dist/src/parties/data-party.js +13 -10
  56. package/dist/src/parties/data-party.js.map +1 -1
  57. package/dist/src/parties/data-party.test.js +18 -17
  58. package/dist/src/parties/data-party.test.js.map +1 -1
  59. package/dist/src/parties/party-factory.d.ts +0 -6
  60. package/dist/src/parties/party-factory.d.ts.map +1 -1
  61. package/dist/src/parties/party-factory.js +17 -45
  62. package/dist/src/parties/party-factory.js.map +1 -1
  63. package/dist/src/parties/party-manager.d.ts.map +1 -1
  64. package/dist/src/parties/party-manager.js +2 -1
  65. package/dist/src/parties/party-manager.js.map +1 -1
  66. package/dist/src/parties/party-manager.test.js +7 -6
  67. package/dist/src/parties/party-manager.test.js.map +1 -1
  68. package/dist/src/pipeline/message-selector.d.ts +2 -2
  69. package/dist/src/pipeline/message-selector.d.ts.map +1 -1
  70. package/dist/src/pipeline/message-selector.js +29 -29
  71. package/dist/src/pipeline/message-selector.js.map +1 -1
  72. package/dist/src/pipeline/metadata-store.d.ts +3 -3
  73. package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
  74. package/dist/src/pipeline/metadata-store.js +5 -5
  75. package/dist/src/pipeline/metadata-store.js.map +1 -1
  76. package/dist/src/pipeline/metadata-store.test.js +8 -4
  77. package/dist/src/pipeline/metadata-store.test.js.map +1 -1
  78. package/dist/src/pipeline/party-core.d.ts +3 -2
  79. package/dist/src/pipeline/party-core.d.ts.map +1 -1
  80. package/dist/src/pipeline/party-core.js +5 -4
  81. package/dist/src/pipeline/party-core.js.map +1 -1
  82. package/dist/src/pipeline/party-core.test.js +17 -16
  83. package/dist/src/pipeline/party-core.test.js.map +1 -1
  84. package/dist/src/pipeline/party-processor.d.ts +21 -9
  85. package/dist/src/pipeline/party-processor.d.ts.map +1 -1
  86. package/dist/src/pipeline/party-processor.js +0 -8
  87. package/dist/src/pipeline/party-processor.js.map +1 -1
  88. package/dist/src/pipeline/pipeline.d.ts +2 -4
  89. package/dist/src/pipeline/pipeline.d.ts.map +1 -1
  90. package/dist/src/pipeline/pipeline.js +0 -3
  91. package/dist/src/pipeline/pipeline.js.map +1 -1
  92. package/dist/src/pipeline/pipeline.test.js +2 -2
  93. package/dist/src/pipeline/pipeline.test.js.map +1 -1
  94. package/dist/src/protocol/auth-plugin.d.ts +1 -1
  95. package/dist/src/protocol/auth-plugin.d.ts.map +1 -1
  96. package/dist/src/protocol/auth-plugin.js +1 -3
  97. package/dist/src/protocol/auth-plugin.js.map +1 -1
  98. package/dist/src/protocol/authenticator.d.ts +4 -4
  99. package/dist/src/protocol/authenticator.d.ts.map +1 -1
  100. package/dist/src/protocol/authenticator.js +12 -16
  101. package/dist/src/protocol/authenticator.js.map +1 -1
  102. package/dist/src/protocol/authenticator.test.js +1 -4
  103. package/dist/src/protocol/authenticator.test.js.map +1 -1
  104. package/dist/src/protocol/halo-recovery-plugin.d.ts +1 -1
  105. package/dist/src/protocol/halo-recovery-plugin.d.ts.map +1 -1
  106. package/dist/src/protocol/halo-recovery-plugin.js +1 -3
  107. package/dist/src/protocol/halo-recovery-plugin.js.map +1 -1
  108. package/dist/src/protocol/identity-credentials.d.ts +2 -2
  109. package/dist/src/protocol/identity-credentials.d.ts.map +1 -1
  110. package/dist/src/protocol/identity-credentials.js +4 -4
  111. package/dist/src/protocol/identity-credentials.js.map +1 -1
  112. package/dist/src/protocol/offline-invitation-plugin.d.ts +1 -1
  113. package/dist/src/protocol/offline-invitation-plugin.d.ts.map +1 -1
  114. package/dist/src/protocol/offline-invitation-plugin.js +1 -3
  115. package/dist/src/protocol/offline-invitation-plugin.js.map +1 -1
  116. package/dist/src/protocol/party-protocol-factory.d.ts +1 -14
  117. package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
  118. package/dist/src/protocol/party-protocol-factory.js +2 -55
  119. package/dist/src/protocol/party-protocol-factory.js.map +1 -1
  120. package/dist/src/protocol/replicator-plugin.d.ts +7 -0
  121. package/dist/src/protocol/replicator-plugin.d.ts.map +1 -0
  122. package/dist/src/protocol/replicator-plugin.js +36 -0
  123. package/dist/src/protocol/replicator-plugin.js.map +1 -0
  124. package/dist/src/snapshots/snapshot-generator.d.ts +1 -1
  125. package/dist/src/snapshots/snapshot-generator.d.ts.map +1 -1
  126. package/dist/src/snapshots/snapshot-generator.js +13 -15
  127. package/dist/src/snapshots/snapshot-generator.js.map +1 -1
  128. package/dist/src/snapshots/snapshot-store.d.ts +3 -3
  129. package/dist/src/snapshots/snapshot-store.d.ts.map +1 -1
  130. package/dist/src/snapshots/snapshot-store.js +5 -5
  131. package/dist/src/snapshots/snapshot-store.js.map +1 -1
  132. package/dist/src/snapshots/snapshot-store.test.js +1 -1
  133. package/dist/src/snapshots/snapshot-store.test.js.map +1 -1
  134. package/dist/src/testing/benchmark.test.d.ts +2 -0
  135. package/dist/src/testing/benchmark.test.d.ts.map +1 -0
  136. package/dist/src/testing/benchmark.test.js +25 -0
  137. package/dist/src/testing/benchmark.test.js.map +1 -0
  138. package/dist/src/testing/testing-factories.js +2 -2
  139. package/dist/src/testing/testing-factories.js.map +1 -1
  140. package/dist/tsconfig.tsbuildinfo +1 -1
  141. package/package.json +18 -18
  142. package/src/api/selection/queries.ts +14 -18
  143. package/src/api/selection/selection.test.ts +4 -12
  144. package/src/api/selection/selection.ts +1 -7
  145. package/src/database/item-demuxer.ts +2 -4
  146. package/src/database/item-manager.ts +2 -2
  147. package/src/database/testing.ts +1 -1
  148. package/src/echo.ts +8 -18
  149. package/src/halo/halo-factory.ts +6 -18
  150. package/src/halo/halo-party.ts +12 -6
  151. package/src/halo/halo.test.ts +4 -3
  152. package/src/halo/identity.ts +2 -2
  153. package/src/halo/party-opener.ts +2 -2
  154. package/src/halo/preferences.ts +7 -10
  155. package/src/invitations/greeting-protocol-provider.ts +5 -9
  156. package/src/invitations/greeting-responder.ts +15 -17
  157. package/src/invitations/invitation-factory.ts +8 -5
  158. package/src/invitations/offline-invitation-claimer.ts +5 -7
  159. package/src/parties/data-party.test.ts +19 -17
  160. package/src/parties/data-party.ts +15 -10
  161. package/src/parties/party-factory.ts +23 -69
  162. package/src/parties/party-manager.test.ts +9 -6
  163. package/src/parties/party-manager.ts +2 -1
  164. package/src/pipeline/message-selector.ts +30 -34
  165. package/src/pipeline/metadata-store.test.ts +8 -4
  166. package/src/pipeline/metadata-store.ts +5 -5
  167. package/src/pipeline/party-core.test.ts +19 -22
  168. package/src/pipeline/party-core.ts +7 -7
  169. package/src/pipeline/party-processor.ts +23 -15
  170. package/src/pipeline/pipeline.test.ts +2 -2
  171. package/src/pipeline/pipeline.ts +2 -6
  172. package/src/protocol/auth-plugin.ts +1 -3
  173. package/src/protocol/authenticator.test.ts +1 -4
  174. package/src/protocol/authenticator.ts +33 -33
  175. package/src/protocol/halo-recovery-plugin.ts +4 -6
  176. package/src/protocol/identity-credentials.ts +4 -4
  177. package/src/protocol/offline-invitation-plugin.ts +4 -6
  178. package/src/protocol/party-protocol-factory.ts +3 -56
  179. package/src/protocol/replicator-plugin.ts +37 -0
  180. package/src/snapshots/snapshot-generator.ts +12 -16
  181. package/src/snapshots/snapshot-store.test.ts +1 -1
  182. package/src/snapshots/snapshot-store.ts +5 -6
  183. package/src/testing/benchmark.test.ts +30 -0
  184. package/src/testing/testing-factories.ts +2 -2
@@ -12,22 +12,40 @@ import {
12
12
  PartyState,
13
13
  Message as HaloMessage,
14
14
  IdentityEventType,
15
- PartyEventType
15
+ PartyEventType,
16
+ SignedMessage
16
17
  } from '@dxos/credentials';
17
18
  import { PublicKey } from '@dxos/crypto';
18
- import { FeedKey, FeedWriter, IHaloStream, PartyKey, HaloStateSnapshot, WriteReceipt } from '@dxos/echo-protocol';
19
+ import { FeedKey, IHaloStream, PartyKey, HaloStateSnapshot } from '@dxos/echo-protocol';
19
20
  import { jsonReplacer } from '@dxos/util';
20
21
 
21
22
  const log = debug('dxos:echo-db:party-processor');
22
23
 
24
+ export interface CredentialProcessor {
25
+ processMessage (message: IHaloStream): Promise<void>
26
+ }
27
+
28
+ export interface PartyStateProvider {
29
+ partyKey: PublicKey
30
+
31
+ /**
32
+ * Whether PartyGenesis was already processed.
33
+ */
34
+ genesisRequired: boolean
35
+ memberKeys: PublicKey[]
36
+ feedKeys: PublicKey[]
37
+ getFeedOwningMember (feedKey: FeedKey): PublicKey | undefined
38
+ isFeedAdmitted (feedKey: FeedKey): boolean
39
+
40
+ getOfflineInvitation (invitationID: Buffer): SignedMessage | undefined
41
+ }
42
+
23
43
  /**
24
44
  * TODO(burdon): Wrapper/Bridge between HALO APIs.
25
45
  */
26
- export class PartyProcessor {
46
+ export class PartyProcessor implements CredentialProcessor, PartyStateProvider {
27
47
  private readonly _state: PartyState;
28
48
 
29
- private _outboundHaloStream: FeedWriter<HaloMessage> | undefined;
30
-
31
49
  readonly feedAdded = new Event<FeedKey>()
32
50
 
33
51
  public readonly keyOrInfoAdded = new Event<PublicKey>();
@@ -124,16 +142,6 @@ export class PartyProcessor {
124
142
  await this._state.processMessages([data]);
125
143
  }
126
144
 
127
- setOutboundStream (stream: FeedWriter<HaloMessage>) {
128
- this._outboundHaloStream = stream;
129
- }
130
-
131
- async writeHaloMessage (message: HaloMessage): Promise<WriteReceipt> {
132
- assert(this._outboundHaloStream, 'Party is closed or read-only');
133
- // TODO(marik-d): Wait for the message to be processed?
134
- return this._outboundHaloStream.write(message);
135
- }
136
-
137
145
  makeSnapshot (): HaloStateSnapshot {
138
146
  return {
139
147
  messages: this._haloMessages
@@ -25,7 +25,7 @@ const log = debug('dxos:echo:pipeline:test');
25
25
  describe('pipeline', () => {
26
26
  test('streams', async () => {
27
27
  const storage = createStorage('', StorageType.RAM);
28
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
28
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
29
29
  const feedKeys: Uint8Array[] = [];
30
30
  const feedSelector: FeedSelector = descriptor => !!feedKeys.find(key => descriptor.key.equals(key));
31
31
  const feedReadStream = new FeedStoreIterator(feedSelector, () => 0, new Timeframe());
@@ -87,7 +87,7 @@ describe('pipeline', () => {
87
87
 
88
88
  test('writing', async () => {
89
89
  const storage = createStorage('', StorageType.RAM);
90
- const feedStore = new FeedStore(storage, { valueEncoding: codec });
90
+ const feedStore = new FeedStore(storage.directory('feed'), { valueEncoding: codec });
91
91
  const feedReadStream = new FeedStoreIterator(() => true, () => 0, new Timeframe());
92
92
 
93
93
  const { publicKey, secretKey } = createKeyPair();
@@ -17,7 +17,7 @@ import { createReadable } from '@dxos/feed-store';
17
17
  import { jsonReplacer } from '@dxos/util';
18
18
 
19
19
  import { TimeframeClock } from '../database';
20
- import { PartyProcessor } from './party-processor';
20
+ import { CredentialProcessor, PartyStateProvider } from './party-processor';
21
21
 
22
22
  interface Options {
23
23
  readLogger?: (msg: any) => void
@@ -55,17 +55,13 @@ export class Pipeline {
55
55
  * @param _options
56
56
  */
57
57
  constructor (
58
- private readonly _partyProcessor: PartyProcessor,
58
+ private readonly _partyProcessor: CredentialProcessor & PartyStateProvider,
59
59
  private readonly _feedStorIterator: FeedStoreIterator,
60
60
  private readonly _timeframeClock: TimeframeClock,
61
61
  private readonly _feedWriter?: FeedWriter<FeedMessage>,
62
62
  private readonly _options: Options = {}
63
63
  ) {}
64
64
 
65
- get partyKey () {
66
- return this._partyProcessor.partyKey;
67
- }
68
-
69
65
  get isOpen () {
70
66
  return this._inboundEchoStream !== undefined;
71
67
  }
@@ -9,6 +9,4 @@ import { Replicator } from '@dxos/protocol-plugin-replicator';
9
9
  /**
10
10
  * Creates authenticator network-protocol plugin that guards access to the replicator.
11
11
  */
12
- export function createAuthPlugin (authenticator: Authenticator, peerId: PublicKey) {
13
- return new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
14
- }
12
+ export const createAuthPlugin = (authenticator: Authenticator, peerId: PublicKey) => new AuthPlugin(peerId.asBuffer(), authenticator, [Replicator.extension]);
@@ -6,7 +6,6 @@ import expect from 'expect';
6
6
  import { it as test } from 'mocha';
7
7
 
8
8
  import { createAuthMessage, createKeyAdmitMessage, createPartyGenesisMessage, Keyring, KeyType } from '@dxos/credentials';
9
- import { MockFeedWriter } from '@dxos/echo-protocol';
10
9
 
11
10
  import { PartyProcessor } from '../pipeline';
12
11
  import { createAuthenticator } from './authenticator';
@@ -23,8 +22,6 @@ describe('authenticator', () => {
23
22
  const signer = CredentialsSigner.createDirectDeviceSigner(keyring);
24
23
 
25
24
  const partyProcessor = new PartyProcessor(partyKey.publicKey);
26
- const feed = new MockFeedWriter();
27
- partyProcessor.setOutboundStream(feed);
28
25
  await partyProcessor.processMessage({
29
26
  data: createPartyGenesisMessage(
30
27
  keyring,
@@ -53,7 +50,7 @@ describe('authenticator', () => {
53
50
  meta: {} as any
54
51
  });
55
52
 
56
- const authenticator = createAuthenticator(partyProcessor, signer);
53
+ const authenticator = createAuthenticator(partyProcessor, signer, null as any);
57
54
  const credential = createAuthMessage(
58
55
  keyring,
59
56
  partyKey.publicKey,
@@ -4,27 +4,29 @@
4
4
 
5
5
  import debug from 'debug';
6
6
 
7
- import { Authenticator, codec, createAuthMessage, createEnvelopeMessage, createFeedAdmitMessage, PartyAuthenticator } from '@dxos/credentials';
8
- import { FeedKey, PartyKey } from '@dxos/echo-protocol';
7
+ import { Message as HaloMessage, Authenticator, codec, createAuthMessage, createEnvelopeMessage, createFeedAdmitMessage, PartyAuthenticator } from '@dxos/credentials';
8
+ import { FeedKey, FeedWriter, PartyKey } from '@dxos/echo-protocol';
9
9
 
10
10
  import { PartyProcessor } from '../pipeline';
11
11
  import { CredentialsSigner } from './credentials-signer';
12
12
 
13
13
  const log = debug('dxos:echo-db:authenticator');
14
14
 
15
- export function createAuthenticator (partyProcessor: PartyProcessor, credentialsSigner: CredentialsSigner): Authenticator {
16
- return new PartyAuthenticator(partyProcessor.state, async auth => {
17
- if (auth.feedAdmit && auth.feedKey && !partyProcessor.isFeedAdmitted(auth.feedKey)) {
18
- log(`Admitting feed of authenticated member: ${auth.feedKey}`);
19
- await partyProcessor.writeHaloMessage(createEnvelopeMessage(
20
- credentialsSigner.signer,
21
- partyProcessor.partyKey,
22
- auth.feedAdmit,
23
- [credentialsSigner.getDeviceSigningKeys()]
24
- ));
25
- }
26
- });
27
- }
15
+ export const createAuthenticator = (
16
+ partyProcessor: PartyProcessor,
17
+ credentialsSigner: CredentialsSigner,
18
+ credentialsWriter: FeedWriter<HaloMessage>
19
+ ): Authenticator => new PartyAuthenticator(partyProcessor.state, async auth => {
20
+ if (auth.feedAdmit && auth.feedKey && !partyProcessor.isFeedAdmitted(auth.feedKey)) {
21
+ log(`Admitting feed of authenticated member: ${auth.feedKey}`);
22
+ await credentialsWriter.write(createEnvelopeMessage(
23
+ credentialsSigner.signer,
24
+ partyProcessor.partyKey,
25
+ auth.feedAdmit,
26
+ [credentialsSigner.getDeviceSigningKeys()]
27
+ ));
28
+ }
29
+ });
28
30
 
29
31
  export interface CredentialsProvider {
30
32
  /**
@@ -33,24 +35,22 @@ export interface CredentialsProvider {
33
35
  get (): Buffer
34
36
  }
35
37
 
36
- export function createCredentialsProvider (credentialsSigner: CredentialsSigner, partyKey: PartyKey, feedKey: FeedKey): CredentialsProvider {
37
- return {
38
- get: () => {
39
- const authMessage = createAuthMessage(
38
+ export const createCredentialsProvider = (credentialsSigner: CredentialsSigner, partyKey: PartyKey, feedKey: FeedKey): CredentialsProvider => ({
39
+ get: () => {
40
+ const authMessage = createAuthMessage(
41
+ credentialsSigner.signer,
42
+ partyKey,
43
+ credentialsSigner.getIdentityKey(),
44
+ credentialsSigner.getDeviceSigningKeys(),
45
+ feedKey,
46
+ undefined,
47
+ createFeedAdmitMessage(
40
48
  credentialsSigner.signer,
41
49
  partyKey,
42
- credentialsSigner.getIdentityKey(),
43
- credentialsSigner.getDeviceSigningKeys(),
44
50
  feedKey,
45
- undefined,
46
- createFeedAdmitMessage(
47
- credentialsSigner.signer,
48
- partyKey,
49
- feedKey,
50
- [feedKey, credentialsSigner.getDeviceSigningKeys()]
51
- )
52
- );
53
- return Buffer.from(codec.encode(authMessage));
54
- }
55
- };
56
- }
51
+ [feedKey, credentialsSigner.getDeviceSigningKeys()]
52
+ )
53
+ );
54
+ return Buffer.from(codec.encode(authMessage));
55
+ }
56
+ });
@@ -12,9 +12,7 @@ import { HaloRecoveryInitiator, InvitationFactory } from '../invitations';
12
12
  * Plugin is intended to be used in HALO party swarm.
13
13
  *
14
14
  */
15
- export function createHaloRecoveryPlugin (identityKey: PublicKey, invitationFactory: InvitationFactory, peerId: PublicKey) {
16
- return new GreetingCommandPlugin(
17
- peerId.asBuffer(),
18
- HaloRecoveryInitiator.createHaloInvitationClaimHandler(identityKey, invitationFactory)
19
- );
20
- }
15
+ export const createHaloRecoveryPlugin = (identityKey: PublicKey, invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
16
+ peerId.asBuffer(),
17
+ HaloRecoveryInitiator.createHaloInvitationClaimHandler(identityKey, invitationFactory)
18
+ );
@@ -25,7 +25,7 @@ export interface IdentityCredentials {
25
25
 
26
26
  export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
27
27
 
28
- export async function createTestIdentityCredentials (keyring: Keyring): Promise<IdentityCredentials> {
28
+ export const createTestIdentityCredentials = async (keyring: Keyring): Promise<IdentityCredentials> => {
29
29
  const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
30
30
  const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
31
31
  const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
@@ -53,9 +53,9 @@ export async function createTestIdentityCredentials (keyring: Keyring): Promise<
53
53
  preferences: undefined,
54
54
  contacts: undefined
55
55
  };
56
- }
56
+ };
57
57
 
58
- export async function deriveTestDeviceCredentials (identity: IdentityCredentials): Promise<IdentityCredentials> {
58
+ export const deriveTestDeviceCredentials = async (identity: IdentityCredentials): Promise<IdentityCredentials> => {
59
59
  const deviceKey = await identity.keyring.createKeyRecord({ type: KeyType.DEVICE });
60
60
  const keyAdmit = createKeyAdmitMessage(identity.keyring, identity.identityKey.publicKey, deviceKey, [identity.identityKey]);
61
61
 
@@ -75,4 +75,4 @@ export async function deriveTestDeviceCredentials (identity: IdentityCredentials
75
75
  deviceKeyChain
76
76
  )
77
77
  };
78
- }
78
+ };
@@ -11,9 +11,7 @@ import { InvitationFactory, OfflineInvitationClaimer } from '../invitations';
11
11
  * Creates network protocol plugin that allows peers to claim offline invitations.
12
12
  * Plugin is intended to be used in data-party swarms.
13
13
  */
14
- export function createOfflineInvitationPlugin (invitationFactory: InvitationFactory, peerId: PublicKey) {
15
- return new GreetingCommandPlugin(
16
- peerId.asBuffer(),
17
- OfflineInvitationClaimer.createOfflineInvitationClaimHandler(invitationFactory)
18
- );
19
- }
14
+ export const createOfflineInvitationPlugin = (invitationFactory: InvitationFactory, peerId: PublicKey) => new GreetingCommandPlugin(
15
+ peerId.asBuffer(),
16
+ OfflineInvitationClaimer.createOfflineInvitationClaimHandler(invitationFactory)
17
+ );
@@ -4,17 +4,13 @@
4
4
 
5
5
  import debug from 'debug';
6
6
 
7
- import { synchronized } from '@dxos/async';
8
7
  import { discoveryKey, keyToString, PublicKey } from '@dxos/crypto';
9
- import { FeedKey, PartyKey } from '@dxos/echo-protocol';
10
- import type { HypercoreFeed } from '@dxos/feed-store';
8
+ import { PartyKey } from '@dxos/echo-protocol';
11
9
  import { Protocol } from '@dxos/mesh-protocol';
12
10
  import { MMSTTopology, NetworkManager, Plugin } from '@dxos/network-manager';
13
11
  import { PresencePlugin } from '@dxos/protocol-plugin-presence';
14
- import { Replicator } from '@dxos/protocol-plugin-replicator';
15
12
 
16
13
  import { CredentialsProvider } from '.';
17
- import { PartyFeedProvider } from '../pipeline/party-feed-provider';
18
14
 
19
15
  const log = debug('dxos:echo-db:party-protocol-factory');
20
16
 
@@ -23,21 +19,15 @@ const log = debug('dxos:echo-db:party-protocol-factory');
23
19
  */
24
20
  export class PartyProtocolFactory {
25
21
  private readonly _presencePlugin = new PresencePlugin(this._peerId.asBuffer());
26
- private readonly _replicatorProtocolPluginFactory: ReplicatorProtocolPluginFactory;
27
22
 
28
23
  private _started = false;
29
24
 
30
25
  constructor (
31
26
  private readonly _partyKey: PartyKey,
32
27
  private readonly _networkManager: NetworkManager,
33
- private readonly _feedProvider: PartyFeedProvider,
34
28
  private readonly _peerId: PublicKey,
35
29
  private readonly _credentials: CredentialsProvider
36
- ) {
37
- // Replication.
38
- this._replicatorProtocolPluginFactory =
39
- new ReplicatorProtocolPluginFactory(this._feedProvider);
40
- }
30
+ ) {}
41
31
 
42
32
  async start (plugins: Plugin[]) {
43
33
  if (this._started) {
@@ -73,9 +63,8 @@ export class PartyProtocolFactory {
73
63
  await this._networkManager.leaveProtocolSwarm(this._partyKey);
74
64
  }
75
65
 
76
- private _createProtocol (channel: any, opts: {initiator: boolean}, extraPlugins: Plugin[]) {
66
+ private _createProtocol (channel: any, opts: { initiator: boolean }, extraPlugins: Plugin[]) {
77
67
  const plugins: Plugin[] = [
78
- ...this._replicatorProtocolPluginFactory.createPlugins(),
79
68
  ...extraPlugins,
80
69
  this._presencePlugin
81
70
  ];
@@ -118,45 +107,3 @@ export class PartyProtocolFactory {
118
107
  return protocol;
119
108
  }
120
109
  }
121
-
122
- /**
123
- * Creates the protocol plugin for feed replication.
124
- */
125
- export class ReplicatorProtocolPluginFactory {
126
- constructor (
127
- private readonly _feedProvider: PartyFeedProvider
128
- ) {}
129
-
130
- createPlugins () {
131
- return [
132
- new Replicator({
133
- load: async () => {
134
- const feeds = this._feedProvider.getFeeds();
135
- log(`Loading feeds: ${feeds.map(feed => keyToString(feed.key))}`);
136
- return feeds.map((feed) => ({ discoveryKey: feed.feed.discoveryKey }));
137
- },
138
-
139
- subscribe: (addFeedToReplicatedSet: (feed: any) => void) => {
140
- return this._feedProvider.feedOpened.on(async (feed) => {
141
- log(`Adding feed: ${feed.key.toHex()}`);
142
- addFeedToReplicatedSet({ discoveryKey: feed.feed.discoveryKey });
143
- });
144
- },
145
-
146
- replicate: async (remoteFeeds, info) => {
147
- // We can ignore remoteFeeds entirely, since the set of feeds we want to replicate is dictated by the Party.
148
- // TODO(telackey): Why are we opening feeds? Necessary or belt/braces thinking, or because open party does it?
149
- const feeds = this._feedProvider.getFeeds();
150
- log(`Replicating: peerId=${info.session}; feeds=${feeds.map(feed => feed.key.toHex())}`);
151
- return feeds.map(feed => feed.feed);
152
- }
153
- })
154
- ];
155
- }
156
-
157
- @synchronized
158
- private async _openFeed (key: FeedKey): Promise<HypercoreFeed> {
159
- const descriptor = await this._feedProvider.createOrOpenReadOnlyFeed(key);
160
- return descriptor.feed;
161
- }
162
- }
@@ -0,0 +1,37 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import debug from 'debug';
6
+
7
+ import { keyToString } from '@dxos/crypto';
8
+ import { Replicator } from '@dxos/protocol-plugin-replicator';
9
+
10
+ import { PartyFeedProvider } from '../pipeline';
11
+
12
+ const log = debug('dxos:echo-db:protocol:replicator');
13
+
14
+ /**
15
+ * Creates the protocol plugin for feed replication.
16
+ */
17
+ export const createReplicatorPlugin = (feedProvider: PartyFeedProvider) =>
18
+ new Replicator({
19
+ load: async () => {
20
+ const feeds = feedProvider.getFeeds();
21
+ log(`Loading feeds: ${feeds.map(feed => keyToString(feed.key))}`);
22
+ return feeds.map((feed) => ({ discoveryKey: feed.feed.discoveryKey }));
23
+ },
24
+
25
+ subscribe: (addFeedToReplicatedSet: (feed: any) => void) => feedProvider.feedOpened.on(async (feed) => {
26
+ log(`Adding feed: ${feed.key.toHex()}`);
27
+ addFeedToReplicatedSet({ discoveryKey: feed.feed.discoveryKey });
28
+ }),
29
+
30
+ replicate: async (remoteFeeds, info) => {
31
+ // We can ignore remoteFeeds entirely, since the set of feeds we want to replicate is dictated by the Party.
32
+ // TODO(telackey): Why are we opening feeds? Necessary or belt/braces thinking, or because open party does it?
33
+ const feeds = feedProvider.getFeeds();
34
+ log(`Replicating: peerId=${info.session}; feeds=${feeds.map(feed => feed.key.toHex())}`);
35
+ return feeds.map(feed => feed.feed);
36
+ }
37
+ });
@@ -10,20 +10,16 @@ import { SnapshotStore } from './snapshot-store';
10
10
 
11
11
  const log = debug('dxos:snapshot-generator');
12
12
 
13
- export function createAutomaticSnapshots (
14
- party: PartyCore, clock: TimeframeClock, store: SnapshotStore, interval: number
15
- ) {
16
- return clock.update.on(async timeframe => {
17
- const totalMessages = timeframe.totalMessages();
18
- if (totalMessages > 0 && totalMessages % interval === 0) {
19
- log(`Saving snapshot of ${party.key.humanize()}...`);
20
- try {
21
- const snapshot = party.createSnapshot();
22
- await store.save(snapshot);
23
- } catch (err: any) {
24
- console.error('Failed to save snapshot');
25
- console.error(err);
26
- }
13
+ export const createAutomaticSnapshots = (party: PartyCore, clock: TimeframeClock, store: SnapshotStore, interval: number) => clock.update.on(async timeframe => {
14
+ const totalMessages = timeframe.totalMessages();
15
+ if (totalMessages > 0 && totalMessages % interval === 0) {
16
+ log(`Saving snapshot of ${party.key.humanize()}...`);
17
+ try {
18
+ const snapshot = party.createSnapshot();
19
+ await store.save(snapshot);
20
+ } catch (err: any) {
21
+ console.error('Failed to save snapshot');
22
+ console.error(err);
27
23
  }
28
- });
29
- }
24
+ }
25
+ });
@@ -15,7 +15,7 @@ const createPublicKey = () => PublicKey.from(createKeyPair().publicKey);
15
15
 
16
16
  describe('SnapshotStore', () => {
17
17
  test('in-memory', async () => {
18
- const store = new SnapshotStore(createStorage('snapshots', StorageType.RAM));
18
+ const store = new SnapshotStore(createStorage('', StorageType.RAM).directory('snapshots'));
19
19
 
20
20
  const key1 = createPublicKey();
21
21
  const key2 = createPublicKey();
@@ -7,10 +7,9 @@ import debug from 'debug';
7
7
 
8
8
  import { keyToString } from '@dxos/crypto';
9
9
  import { schema, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
10
- import { Storage } from '@dxos/random-access-multi-storage';
10
+ import { Directory } from '@dxos/random-access-multi-storage';
11
11
 
12
12
  const log = debug('dxos:snapshot-store');
13
-
14
13
  /**
15
14
  * Stores party snapshots. Takes any `random-access-storage` compatible backend.
16
15
  *
@@ -18,11 +17,11 @@ const log = debug('dxos:snapshot-store');
18
17
  */
19
18
  export class SnapshotStore {
20
19
  constructor (
21
- private readonly _storage: Storage
20
+ private readonly _directory: Directory
22
21
  ) {}
23
22
 
24
23
  async load (partyKey: PartyKey): Promise<PartySnapshot | undefined> {
25
- const file = this._storage.createOrOpen(partyKey.toHex());
24
+ const file = this._directory.createOrOpen(partyKey.toHex());
26
25
 
27
26
  try {
28
27
  const { size } = await file.stat();
@@ -45,7 +44,7 @@ export class SnapshotStore {
45
44
 
46
45
  async save (snapshot: PartySnapshot) {
47
46
  assert(snapshot.partyKey);
48
- const file = this._storage.createOrOpen(keyToString(snapshot.partyKey), { truncate: true, size: 0 });
47
+ const file = this._directory.createOrOpen(keyToString(snapshot.partyKey), { truncate: true, size: 0 });
49
48
 
50
49
  try {
51
50
  const data = schema.getCodecForType('dxos.echo.snapshot.PartySnapshot').encode(snapshot);
@@ -60,6 +59,6 @@ export class SnapshotStore {
60
59
  */
61
60
  async clear () {
62
61
  log('Clearing all snapshots..');
63
- await this._storage.destroy();
62
+ await this._directory.destroy();
64
63
  }
65
64
  }
@@ -0,0 +1,30 @@
1
+ //
2
+ // Copyright 2022 DXOS.org
3
+ //
4
+
5
+ import { ObjectModel } from '@dxos/object-model';
6
+
7
+ import { ECHO } from '../echo';
8
+
9
+ const ITEMS = 100;
10
+ const MUTATIONS = 1000;
11
+
12
+ it.skip('Database benchmark', async () => {
13
+ const echo = new ECHO({ snapshots: false });
14
+ await echo.open();
15
+ await echo.halo.createProfile();
16
+ const party = await echo.createParty();
17
+
18
+ const start = Date.now();
19
+ for (let i = 0; i < ITEMS; i++) {
20
+ const item = await party.database.createItem({ model: ObjectModel, type: 'test:item' });
21
+
22
+ for (let j = 0; j < MUTATIONS; j++) {
23
+ await item.model.set(`key${j % 100}`, `value-${j}`);
24
+ }
25
+
26
+ console.log(`${i * MUTATIONS}/${ITEMS * MUTATIONS} ${((Date.now() - start) / ((i + 1) * MUTATIONS / 1000)).toFixed(1)} µs/mut ${((i + 1) * MUTATIONS / (Date.now() - start) * 1000).toFixed(1)} mut/s`);
27
+ }
28
+
29
+ await echo.close();
30
+ });
@@ -22,10 +22,10 @@ export type TestPeer = Awaited<ReturnType<typeof createTestInstance>>;
22
22
 
23
23
  export type WithTestMeta<T> = T & { testMeta: TestPeer }
24
24
 
25
- function addTestMeta<T> (obj: T, meta: TestPeer): WithTestMeta<T> {
25
+ const addTestMeta = <T>(obj: T, meta: TestPeer): WithTestMeta<T> => {
26
26
  (obj as any).testMeta = meta;
27
27
  return obj as any;
28
- }
28
+ };
29
29
 
30
30
  /**
31
31
  * Creates a number of test ECHO instances and a party that's shared between all of them.