@ibgib/core-gib 0.1.25 → 0.1.27

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 (46) hide show
  1. package/dist/common/other/ibgib-helper.d.mts +1 -1
  2. package/dist/common/other/ibgib-helper.d.mts.map +1 -1
  3. package/dist/common/other/ibgib-helper.mjs.map +1 -1
  4. package/dist/sync/sync-constants.d.mts +1 -0
  5. package/dist/sync/sync-constants.d.mts.map +1 -1
  6. package/dist/sync/sync-constants.mjs +1 -0
  7. package/dist/sync/sync-constants.mjs.map +1 -1
  8. package/dist/sync/sync-helpers.d.mts +21 -1
  9. package/dist/sync/sync-helpers.d.mts.map +1 -1
  10. package/dist/sync/sync-helpers.mjs +137 -4
  11. package/dist/sync/sync-helpers.mjs.map +1 -1
  12. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts +0 -2
  13. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.d.mts.map +1 -1
  14. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs +169 -62
  15. package/dist/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mjs.map +1 -1
  16. package/dist/sync/sync-peer/sync-peer-v1.d.mts +13 -29
  17. package/dist/sync/sync-peer/sync-peer-v1.d.mts.map +1 -1
  18. package/dist/sync/sync-peer/sync-peer-v1.mjs +18 -57
  19. package/dist/sync/sync-peer/sync-peer-v1.mjs.map +1 -1
  20. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts +15 -1
  21. package/dist/sync/sync-saga-context/sync-saga-context-helpers.d.mts.map +1 -1
  22. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs +77 -7
  23. package/dist/sync/sync-saga-context/sync-saga-context-helpers.mjs.map +1 -1
  24. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts +8 -0
  25. package/dist/sync/sync-saga-context/sync-saga-context-types.d.mts.map +1 -1
  26. package/dist/sync/sync-saga-coordinator.d.mts +76 -17
  27. package/dist/sync/sync-saga-coordinator.d.mts.map +1 -1
  28. package/dist/sync/sync-saga-coordinator.mjs +545 -480
  29. package/dist/sync/sync-saga-coordinator.mjs.map +1 -1
  30. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts +1 -1
  31. package/dist/sync/sync-saga-message/sync-saga-message-types.d.mts.map +1 -1
  32. package/dist/sync/sync-types.d.mts +31 -4
  33. package/dist/sync/sync-types.d.mts.map +1 -1
  34. package/dist/sync/sync-types.mjs +32 -0
  35. package/dist/sync/sync-types.mjs.map +1 -1
  36. package/package.json +2 -2
  37. package/src/common/other/ibgib-helper.mts +1 -1
  38. package/src/sync/sync-constants.mts +1 -0
  39. package/src/sync/sync-helpers.mts +132 -4
  40. package/src/sync/sync-peer/sync-peer-innerspace/sync-peer-innerspace-v1.mts +169 -47
  41. package/src/sync/sync-peer/sync-peer-v1.mts +33 -74
  42. package/src/sync/sync-saga-context/sync-saga-context-helpers.mts +69 -9
  43. package/src/sync/sync-saga-context/sync-saga-context-types.mts +13 -5
  44. package/src/sync/sync-saga-coordinator.mts +628 -530
  45. package/src/sync/sync-saga-message/sync-saga-message-types.mts +18 -18
  46. package/src/sync/sync-types.mts +40 -3
@@ -2,20 +2,28 @@
2
2
  * @module SyncPeerInnerspace_V1
3
3
  */
4
4
 
5
- import { extractErrorMsg, unique } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
5
+ import { delay, extractErrorMsg, pretty, unique } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
6
6
  import { getIbGibAddr } from '@ibgib/ts-gib/dist/helper.mjs';
7
7
  import { IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
8
+ import { IbGib_V1, IbGibData_V1 } from '@ibgib/ts-gib/dist/V1/types.mjs';
9
+ import { isDna } from '@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs';
8
10
 
9
11
  import { GLOBAL_LOG_A_LOT } from '../../../core-constants.mjs';
10
12
  import { IbGibSpaceAny } from '../../../witness/space/space-base-v1.mjs';
11
13
  import { SyncPeer_V1 } from '../sync-peer-v1.mjs';
12
- import { getFromSpace, putInSpace } from '../../../witness/space/space-helper.mjs';
14
+ import { getFromSpace, putInSpace, registerNewIbGib } from '../../../witness/space/space-helper.mjs';
13
15
  import { SyncSagaContextIbGib_V1, } from '../../sync-saga-context/sync-saga-context-types.mjs';
14
16
  import { SyncPeerInnerspaceData_V1, SyncPeerInnerspaceIbGib_V1, SyncPeerInnerspaceOptions, SyncPeerInnerspaceRel8ns_V1 } from './sync-peer-innerspace-types.mjs';
15
17
  import { MetaspaceService } from '../../../witness/space/metaspace/metaspace-types.mjs';
16
18
  import { SyncSagaCoordinator } from '../../sync-saga-coordinator.mjs';
17
19
  import { IbGibSpaceResultData } from '../../../witness/space/space-types.mjs';
18
20
  import { InitializeSyncPeerOpts } from '../sync-peer-types.mjs';
21
+ import { getSyncSagaMessageFromFrame } from '../../sync-saga-message/sync-saga-message-helpers.mjs';
22
+ import { SYNC_STAGE_VALID_VALUES, SyncStage } from '../../sync-constants.mjs';
23
+ import { SyncSagaMessageAckData_V1, SyncSagaMessageCommitData_V1, SyncSagaMessageData_V1, SyncSagaMessageDeltaData_V1, SyncSagaMessageInitData_V1 } from '../../sync-saga-message/sync-saga-message-types.mjs';
24
+ import { getExecutionContext, getSyncSagaFrameDependencyGraph, putInSpace_dnasThenNonDnas } from '../../sync-helpers.mjs';
25
+ import { splitPerTjpAndOrDna, toDto } from '../../../common/other/ibgib-helper.mjs';
26
+ import { SyncExecutionContext } from '../../sync-types.mjs';
19
27
 
20
28
 
21
29
  const logalot = GLOBAL_LOG_A_LOT || true;
@@ -101,69 +109,183 @@ export class SyncPeerInnerspace_V1 extends SyncPeer_V1<InitializeSyncPeerInnersp
101
109
  }
102
110
  }
103
111
 
104
-
105
- protected async push(addrs: IbGibAddr[]): Promise<void> {
106
- const lc = `${this.lc}[${this.push.name}]`;
107
- try {
108
- if (logalot) { console.log(`${lc} starting... (I: 07bce80be18f3259b8a311ed9c4da926)`); }
109
- if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: e1efd1b364cc8a8d985b243878f71e26)`); }
110
-
111
- // silly defensive checks because this has been a ridiculous development cycle
112
- if (!this.opts.senderSpace) { throw new Error(`(UNEXPECTED) this.opts.senderSpace falsy? (E: 503e288168f5d297f4d4e028bc538826)`); }
113
- if (!this.opts.receiverTempSpace) { throw new Error(`(UNEXPECTED) this.opts.receiverTempSpace falsy? (E: 0bd7c1a0ba4868ac7a260e15b504e826)`); }
114
-
115
- await this.transfer({ addrs, from: this.opts.senderSpace, to: this.opts.receiverTempSpace });
116
- } catch (error) {
117
- console.error(`${lc} ${extractErrorMsg(error)}`);
118
- throw error;
119
- } finally {
120
- if (logalot) { console.log(`${lc} complete.`); }
121
- }
122
- }
123
-
124
- protected async pull(addrs: IbGibAddr[]): Promise<void> {
125
- const lc = `${this.lc}[${this.pull.name}]`;
126
- try {
127
- if (logalot) { console.log(`${lc} starting... (I: b16a28ed0dc8f52f1838ee257d9b1126)`); }
128
-
129
- if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: 5a72b83fc1a83bf0f81d19330f575626)`); }
130
-
131
- // silly defensive checks because this has been a ridiculous development cycle
132
- if (!this.opts.receiverSpace) { throw new Error(`(UNEXPECTED) this.opts.receiverSpace falsy? (E: bd2fdfa89ba4c89a185b68e9bb1f1c26)`); }
133
- if (!this.opts.senderTempSpace) { throw new Error(`(UNEXPECTED) this.opts.senderTempSpace falsy? (E: b23fa55713f881493dac4a9835ac7326)`); }
134
-
135
- await this.transfer({ addrs, from: this.opts.receiverSpace, to: this.opts.senderTempSpace });
136
- } catch (error) {
137
- console.error(`${lc} ${extractErrorMsg(error)}`);
138
- throw error;
139
- } finally {
140
- if (logalot) { console.log(`${lc} complete.`); }
141
- }
142
- }
143
-
144
112
  protected async sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined> {
145
113
  const lc = `${this.lc}[${this.sendContextRequest.name}]`;
146
114
  try {
147
115
  if (!this.opts) { throw new Error(`(UNEXPECTED) this.opts falsy? (E: d8b1348e3233810128999596b1fa5826)`); }
148
116
 
149
- const { receiverSpace, receiverCoordinator, receiverMetaspace } = this.opts;
117
+ const {
118
+ senderSpace, senderTempSpace,
119
+ receiverSpace, receiverCoordinator, receiverMetaspace,
120
+ receiverTempSpace
121
+ } = this.opts;
150
122
 
151
123
  if (logalot) { console.log(`${lc} starting...Context: ${getIbGibAddr({ ibGib: context })}`); }
152
124
 
153
- // 0. Validate context (naive, not business logic validation)
125
+ const { sagaFrame } = context;
126
+
127
+ // The context has already been validated, authenticated and authorized at this point.
128
+
129
+ // #region sanity validation assertions
154
130
  if (!context.data) { throw new Error(`(UNEXPECTED) context.data falsy? (E: 1d2ac8a9b991d451e8900588057fe626)`); }
155
131
  if (!context.rel8ns) { throw new Error(`(UNEXPECTED) context.rel8ns falsy? (E: 3508786f0d8880bcadd346282a807826)`); }
156
132
  if (!context.rel8ns.sagaFrame) { throw new Error(`(UNEXPECTED) context.rel8ns.sagaFrame falsy? (E: ac06782ad538be406882605f0a83aa26)`); }
157
133
  if (!context.sagaFrame) { throw new Error(`(UNEXPECTED) context.sagaFrame falsy? (E: 79cd98a6d9b88a591f4596c8bc58ff26)`); }
134
+ if (!sagaFrame.data) { throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: f30e290a8b770e1b387377420ea73a26)`); }
135
+ if (!sagaFrame.rel8ns) { throw new Error(`(UNEXPECTED) sagaFrame.rel8ns falsy? (E: f888caa698b8cf6b4893b7fd6df09726)`); }
136
+ if (!receiverTempSpace) { throw new Error(`(UNEXPECTED) receiverTempSpace falsy? (E: 3b46d838f6fc645c58b29215bfddb826)`); }
137
+ if (!senderTempSpace) { throw new Error(`(UNEXPECTED) senderTempSpace falsy? (E: b187a8f913c2295ae90d7ae2b47b6a26)`); }
138
+ // #endregion sanity validation assertions
139
+
140
+ // let localSpace: IbGibSpaceAny;
141
+ // let localTempSpace: IbGibSpaceAny;
142
+ // let remoteSpace: IbGibSpaceAny;
143
+ // let remoteTempSpace: IbGibSpaceAny;
144
+ // if (getExecutionContext({ sagaFrame: context.sagaFrame }) === SyncExecutionContext.sender) {
145
+ // localSpace = senderSpace;
146
+ // localTempSpace = senderTempSpace;
147
+ // remoteSpace = receiverSpace;
148
+ // remoteTempSpace = receiverTempSpace;
149
+ // } else {
150
+ // localSpace = receiverSpace;
151
+ // localTempSpace = receiverTempSpace;
152
+ // remoteSpace = senderSpace;
153
+ // remoteTempSpace = senderSpace;
154
+ // }
155
+
156
+ const { sagaIbGib: _alreadyHave, msgStones, identities } = await getSyncSagaFrameDependencyGraph({
157
+ sagaIbGib: sagaFrame,
158
+ localSpace: senderSpace,
159
+ });
160
+ if (msgStones.length !== 1) { throw new Error(`(UNEXPECTED) msgStones.length !== 1? we're only geared for a single msg stone that is always present (not 0, not greater than 1) (E: 2d3138ed130f1aca116551889483e826)`); }
161
+ const msg = msgStones[0];
162
+ if (!msg.data) { throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`); }
158
163
 
164
+ // send the context itself, then send the payload ibgibs separately.
165
+ // in this innerspace, this just means putting the control ibgibs
166
+ // first into the receiver durable space, then we will spin off a
167
+ // promise to put any payload ibgibs in the receiver temp space.
168
+ // We'll test a little latency also, to mimic a fuller, two-part
169
+ // sync peer to ensure that other code is acting as expected.
170
+
171
+ // we store inside out, meaning we do the dependencies first and
172
+ // then the higher-level dependents.
173
+ const payloadIbGibsControl = [
174
+ ...identities, msg, sagaFrame, context
175
+ ].map(x => toDto({ ibGib: x }));
176
+ await putInSpace({
177
+ ibGibs: payloadIbGibsControl,
178
+ space: receiverSpace,
179
+ });
180
+ // register yet??
181
+ for (const control of payloadIbGibsControl) {
182
+ await registerNewIbGib({
183
+ ibGib: control,
184
+ space: receiverSpace,
185
+ fnBroadcast: undefined
186
+ });
187
+ }
159
188
 
160
- // if we have push offer requests, start those.
189
+ if (context.payloadIbGibsDomain && context.payloadIbGibsDomain.length > 0) {
190
+ await putInSpace_dnasThenNonDnas({
191
+ ibGibs: context.payloadIbGibsDomain,
192
+ space: receiverTempSpace,
193
+ });
161
194
 
162
- // send the context itself, then send the payload ibgibs separately.
195
+ // no need to register right now, because we're putting into the
196
+ // temp receiver space and we don't register until we commit
197
+ // const { mapWithTjp_NoDna, mapWithTjp_YesDna, mapWithoutTjps } =
198
+ // splitPerTjpAndOrDna({ ibGibs: payload_NonDnas });
199
+ }
200
+
201
+ // at this time, the receiver has received the control ibgibs AND
202
+ // the payload ibgibs. so the receiver coordinator should be ready
203
+ // to do its thing.
163
204
 
205
+ const responseCtx = await receiverCoordinator.continueSync({
206
+ sagaContext: context,
207
+ metaspace: receiverMetaspace,
208
+ mySpace: receiverSpace,
209
+ myTempSpace: receiverTempSpace,
210
+ });
164
211
 
212
+ if (logalot) { console.log(`${lc} receiverCoordinator.continueSync responseCtx: ${responseCtx ? pretty(responseCtx) : 'undefined'} (I: fb2831decde1f2b3589021f85ab19126)`); }
213
+
214
+ if (!responseCtx) {
215
+ if (logalot) { console.log(`${lc} receiver produced undefined response context. (I: 2e1888ffc9e836689d5b171887c36d26)`); }
216
+ return undefined; /* <<<< returns early */
217
+ }
218
+
219
+ // at this point, we have received the full response from the
220
+ // receiver coordinator. That coordinator has put the control ibgibs
221
+ // in its durable space. Now we need to put the response's control
222
+ // ibgibs in the sender's durable space (register them??), spin off
223
+ // the process of any response payloads, and return the context.
224
+
225
+ // get control ibgibs from the receiver space...
226
+ const { msgStones: msgStonesResponse, identities: identitiesResponse } =
227
+ await getSyncSagaFrameDependencyGraph({
228
+ sagaIbGib: responseCtx.sagaFrame,
229
+ localSpace: receiverSpace,
230
+ });
231
+ if (msgStonesResponse.length !== 1) { throw new Error(`(UNEXPECTED) msgStonesResponse.length !== 1? we're only geared for a single msg stone that is always present (not 0, not greater than 1) (E: 2d3138ed130f1aca116551889483e826)`); }
232
+ const msgResponse = msgStonesResponse[0];
233
+ if (!msgResponse.data) { throw new Error(`(UNEXPECTED) sync saga message ibgib.data falsy? (E: 61ec18743988ad3cbab2072d1dd69826)`); }
234
+ const responsePayloadIbGibsControl = [
235
+ ...identities, msgResponse, responseCtx.sagaFrame, context
236
+ ].map(x => toDto({ ibGib: x }));
237
+ // ...put into sender's durable space
238
+ await putInSpace({
239
+ ibGibs: responsePayloadIbGibsControl,
240
+ space: senderSpace,
241
+ });
242
+ // register yet??
243
+ for (const control of responsePayloadIbGibsControl) {
244
+ await registerNewIbGib({
245
+ ibGib: control,
246
+ space: senderSpace,
247
+ fnBroadcast: undefined
248
+ });
249
+ }
250
+
251
+ // spin off the payloads, as that may take a long time
252
+ const payloadIbGibsDomain_response = responseCtx.payloadIbGibsDomain;
253
+ if (payloadIbGibsDomain_response) {
254
+ new Promise<void>(async (resolve, reject) => {
255
+ const lcPut = `${lc}[putPayloadsPromise]`;
256
+ try {
257
+ if (logalot) { console.log(`${lcPut} starting... (I: 4133e736b4c80d2cf94448b87b206826)`); }
258
+
259
+ // 2 seconds...i want to see huge blocks of logs entries for this to see this happening
260
+ const delayMs = 200;
261
+ for (let i = 0; i < 10; i++) {
262
+ console.warn(`${lc} ARTIFICIALLY DELAYING PAYLOADS TO MIMIC TRANSFER LATENCY. REMOVE THIS DELAY!! (W: 5e7b28f1daa82d955897e9d8cdb16f26)`)
263
+ await delay(delayMs);
264
+ }
265
+
266
+
267
+ await putInSpace_dnasThenNonDnas({
268
+ ibGibs: payloadIbGibsDomain_response,
269
+ space: senderTempSpace,
270
+ });
271
+
272
+ if (logalot) { console.log(`${lcPut} complete.`); }
273
+ resolve();
274
+ } catch (error) {
275
+ const errorMsg = `${lcPut} ${extractErrorMsg(error)}`;
276
+ console.error(errorMsg);
277
+ if (logalot) { console.log(`${lcPut} complete. (errored)`); }
278
+ reject(errorMsg);
279
+ }
280
+ }); // spin off
281
+
282
+ /**
283
+ * the caller should be getting these from the observable.
284
+ */
285
+ delete responseCtx.payloadIbGibsDomain;
286
+ }
165
287
 
166
- throw new Error(`not implemented (E: 72840872e252d9f7380f1998b5a0c826)`);
288
+ return responseCtx;
167
289
  } catch (error) {
168
290
  console.error(`${lc} ${extractErrorMsg(error)}`);
169
291
  throw error;
@@ -18,7 +18,7 @@ import { InitializeSyncPeerOpts, SyncPeerData_V1, SyncPeerRel8ns_V1, SyncPeerWit
18
18
  import { LightWitnessBase_V1 } from '../../witness/light-witness-base-v1.mjs';
19
19
  import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
20
20
  import { newupSubject } from '../../common/pubsub/subject/subject-helper.mjs';
21
- import { validateContextAndSagaFrame } from '../sync-saga-context/sync-saga-context-helpers.mjs';
21
+ import { authenticateContext, authorizeContext, validateContextAndSagaFrame } from '../sync-saga-context/sync-saga-context-helpers.mjs';
22
22
  import { getFromSpace } from '../../witness/space/space-helper.mjs';
23
23
 
24
24
  const logalot = GLOBAL_LOG_A_LOT || true;
@@ -178,34 +178,38 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
178
178
  if (validationErrors.length > 0) {
179
179
  throw new Error(`invalid context received. validationErrors: ${validationErrors} (E: 8b34c875c968af29bc433138e57a7826)`);
180
180
  }
181
- const authenticationErrors = await this.authenticateContext({ context });
181
+ const authenticationErrors = await authenticateContext({ context });
182
182
  if (authenticationErrors.length > 0) {
183
183
  throw new Error(`invalid context authentication. authenticationErrors: ${authenticationErrors} (E: da89da5ee1269aeb78952d475d607526)`);
184
184
  }
185
- const authorizationErrors = await this.authorizeContext({ context });
185
+ const authorizationErrors = await authorizeContext({ context });
186
186
  if (authorizationErrors.length > 0) {
187
187
  throw new Error(`invalid context authorization. authorizationErrors: ${authorizationErrors} (E: 8ddc284a758cf10ba829334c1babb826)`);
188
188
  }
189
189
 
190
190
  // at this point, we have a valid, authenticated, authorized context
191
191
 
192
- // 2. EXECUTE: Trigger Remote Processing
193
- const response = await this.sendContextRequest(context);
192
+ await this.ensureReceiverTempSpace();
194
193
 
195
- if (!response) {
196
- if (logalot) { console.log(`${lc} No response from peer.`); }
197
- return undefined;
198
- }
194
+ // execute the transfer of control domain ibgibs & outgoing payload
195
+ // ibgibs...
196
+ const response = await this.sendContextRequest(context);
199
197
 
200
- // at this point, all outgoing payload domain ibgibs have been sent.
201
- // we have received the response context, wherein the sync saga
202
- // frame/msg stone(s) and any keystones should be evolved. Depending
203
- // on the concrete implementation, if there are domain ibgibs to
204
- // receive, they may still be transferring. These will be published
205
- // to this.payloadIbGibsDomainReceived$
198
+ if (response) {
199
+ // at this point, all outgoing payload domain ibgibs have been sent.
200
+ // we have received the response context, wherein the sync saga
201
+ // frame/msg stone(s) and any keystones should be evolved. Depending
202
+ // on the concrete implementation, if there are domain ibgibs to
203
+ // receive, they may still be transferring. These will be published
204
+ // to this.payloadIbGibsDomainReceived$
206
205
 
207
- return response;
206
+ return response;
207
+ } else {
208
+ // response falsy. we could be done, or this could be an error.
209
+ if (logalot) { console.log(`${lc} No response from peer. this may be normal if we just sent the very last commit frame. (I: 1855b7728c8898e1f9c001f8170ba826)`); }
208
210
 
211
+ return undefined;
212
+ }
209
213
  } catch (error) {
210
214
  console.error(`${lc} ${extractErrorMsg(error)}`);
211
215
  throw error;
@@ -215,75 +219,30 @@ export abstract class SyncPeer_V1<TInitializeOpts extends InitializeSyncPeerOpts
215
219
  }
216
220
 
217
221
  /**
222
+ * At this point, this is a validated, authenticated and authorized context
223
+ * to send.
224
+ *
218
225
  * This is responsible for:
219
226
  *
220
- * * sending outgoing {@link context}, the sync saga frame and msg stone(s),
221
- * and identities...
227
+ * * physical sending outgoing {@link context}, the sync saga frame and msg
228
+ * stone(s), and identities...
222
229
  * * AND sending OUTGOING domain ibgibs
223
230
  * {@link SyncSagaContextIbGib_V1.payloadIbGibsDomain}
224
231
  * * getting back the other end's resultant context ibgib, sync saga frame
225
232
  * and msg stone(s), and identities in their entirety...
226
233
  * * AND stream/receiving the RESPONSE payload domain ibgibs, publishing
227
234
  * these to this.payloadIbGibsDomainReceived$.
235
+ * * BUT this should return as soon as the resultant context ibgib comes
236
+ * back.
228
237
  *
229
- * So this returns the RESPONSE context, possibly BEFORE the RESPONSE domain
230
- * ibgibs have been completely received/streamed. The coordinator is responsible
231
- */
232
- protected abstract sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined>;
233
-
234
- /**
235
- * Pushes specific IbGib(s) (by address) from Local to Remote.
238
+ * So this returns the RESPONSE context, possibly BEFORE the response DOMAIN
239
+ * ibgibs have been completely received/streamed. The coordinator is
240
+ * responsible for awaiting this stream.
236
241
  *
237
- * Should NOT have to handle identifying if the remote already has it
238
- * (optimization), because the sync coordinator should be doing this in
239
- * its diffing algorithm.
240
- */
241
- protected abstract push(addrs: IbGibAddr[]): Promise<void>;
242
-
243
- /**
244
- * Primitive: Pulls specific IbGib(s) (by address) from Remote to Local.
245
- */
246
- protected abstract pull(addrs: IbGibAddr[]): Promise<void>;
247
-
248
-
249
-
250
- /**
251
- * move to sync-peer-helpers.mts as a pure function?
252
- */
253
- protected async authenticateContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
254
- const lc = `${this.lc}[${this.authenticateContext.name}]`;
255
- try {
256
- if (logalot) { console.log(`${lc} starting... (I: 2677a482dfa873dcd1aa04a3031ff826)`); }
257
-
258
- console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. // todo: authenticate (v1 must have this after we get merge logic workflow going) (E: bc3a78f2dab18ab64c36d055a4b50526)`);
259
-
260
- return [];
261
- } catch (error) {
262
- console.error(`${lc} ${extractErrorMsg(error)}`);
263
- throw error;
264
- } finally {
265
- if (logalot) { console.log(`${lc} complete.`); }
266
- }
267
- }
268
-
269
- /**
270
- * move to sync-peer-helpers.mts as a pure function?
242
+ * @returns next sync saga context if another round, or undefined if we're
243
+ * done. (might throw if there's an error?)
271
244
  */
272
- protected async authorizeContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
273
- const lc = `${this.lc}[${this.authorizeContext.name}]`;
274
- try {
275
- if (logalot) { console.log(`${lc} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`); }
276
-
277
- console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. authorize business logic (v1 must have this, but later when we are working on admin vs. student)(E: bc3a78f2dab18ab64c36d055a4b50526)`);
278
-
279
- return [];
280
- } catch (error) {
281
- console.error(`${lc} ${extractErrorMsg(error)}`);
282
- throw error;
283
- } finally {
284
- if (logalot) { console.log(`${lc} complete.`); }
285
- }
286
- }
245
+ protected abstract sendContextRequest(context: SyncSagaContextIbGib_V1): Promise<SyncSagaContextIbGib_V1 | undefined>;
287
246
 
288
247
  /**
289
248
  * Abstract accessor to get an IbGib from the Local space/store.
@@ -19,6 +19,7 @@ import {
19
19
  import { IbGibSpaceAny } from '../../witness/space/space-base-v1.mjs';
20
20
  import { putInSpace, registerNewIbGib } from '../../witness/space/space-helper.mjs';
21
21
  import { SyncIbGib_V1 } from '../sync-types.mjs';
22
+ import { validateSyncSagaFrame } from '../sync-helpers.mjs';
22
23
 
23
24
  const logalot = GLOBAL_LOG_A_LOT;
24
25
 
@@ -59,9 +60,10 @@ export async function getSyncSagaContextIb({
59
60
  if (!data) { throw new Error(`data required (E: 839d82138c234b3e89582855594191fe)`); }
60
61
 
61
62
  const payloadCount = data['@payloadAddrsDomain'] ? data['@payloadAddrsDomain'].length : 0;
62
- // sync_sagacontext cmd
63
+
63
64
  const ib = [
64
65
  SYNC_SAGA_CONTEXT_ATOM,
66
+ data.sagaN,
65
67
  payloadCount,
66
68
  ].join(' ');
67
69
 
@@ -88,6 +90,7 @@ export async function parseSyncSagaContextIb({
88
90
  }
89
91
  const [
90
92
  atom,
93
+ sagaNStr,
91
94
  payloadCountStr,
92
95
  ] = parts;
93
96
 
@@ -95,13 +98,19 @@ export async function parseSyncSagaContextIb({
95
98
  throw new Error(`Atom mismatch. Expected ${SYNC_SAGA_CONTEXT_ATOM}. Got ${atom}. (E: 67d71fc0f8d04840b178652309f471f5)`);
96
99
  }
97
100
 
101
+ if (!sagaNStr) { throw new Error(`invalid ib. second piece should be sagaN but is falsy (E: 081ed475aeb8fe25a66f60466b2e5826)`); }
102
+ const sagaN = parseInt(sagaNStr);
103
+ if (isNaN(sagaN)) {
104
+ throw new Error(`sagaNStr is not a number. (E: 3d6b580d5a48c5e03ecec288896e2826)`);
105
+ }
106
+
98
107
  if (!payloadCountStr) { throw new Error(`invalid ib. second piece should be payloadCount but is falsy (E: 0bb7580793d800ca02227828a7294826)`); }
99
108
  const payloadCount = parseInt(payloadCountStr);
100
109
  if (isNaN(payloadCount)) {
101
110
  throw new Error(`payloadCountStr is not a number. (E: 49457814282a44069871630987588722)`);
102
111
  }
103
112
 
104
- return { atom, payloadCount };
113
+ return { atom, sagaN, payloadCount };
105
114
  } catch (error) {
106
115
  console.error(`${lc} ${extractErrorMsg(error)}`);
107
116
  throw error;
@@ -129,6 +138,9 @@ export async function createSyncSagaContext({
129
138
  try {
130
139
  if (logalot) { console.log(`${lc} starting... (I: 6b87bee313e811d1d2fc90e87fbec826)`); }
131
140
 
141
+ if (!sagaFrame.data) { throw new Error(`(UNEXPECTED) sagaFrame.data falsy? (E: 04c49b4cccba6842a8b52e4c6f570726)`); }
142
+ if (!sagaFrame.data.n && sagaFrame.data.n !== 0) { throw new Error(`(UNEXPECTED) sagaFrame.data.n falsy and not 0? (E: 45b508da64a8b28428b11765d684b826)`); }
143
+
132
144
  const date = new Date();
133
145
  const timestamp = getTimestamp(date);
134
146
  const timestampMs = date.getMilliseconds();
@@ -136,6 +148,7 @@ export async function createSyncSagaContext({
136
148
  const data: SyncSagaContextData_V1 = {
137
149
  timestamp,
138
150
  timestampMs,
151
+ sagaN: sagaFrame.data.n,
139
152
  };
140
153
 
141
154
  // Domain Payloads
@@ -215,20 +228,27 @@ export async function validateContextAndSagaFrame({ context }: { context: SyncSa
215
228
  }
216
229
 
217
230
  if (context.sagaFrame) {
218
-
231
+ const sagaFrameErrors =
232
+ await validateSyncSagaFrame({ sagaIbGib: context.sagaFrame });
233
+ sagaFrameErrors.forEach(x => errors.push(x));
219
234
  } else {
220
235
  errors.push(`context.sagaFrame is falsy. (E: b4edd88f4963f493789f83b29ba2df26)`);
221
236
  }
222
237
 
223
- // validate the entire context graph intrinsically, including saga frame, stones, identity(s) (if applicable but not authentication, that will be done in a separate step)
224
-
238
+ // if this is already invalid, we could have intrinsic validation errors, which are a non-starter.
239
+ if (errors.length > 0) { return errors; /* <<<< returns early */ }
225
240
 
241
+ // validate the entire context graph intrinsically, including saga frame, stones, identity(s) (if applicable but not authentication, that will be done in a separate step)
226
242
 
227
- // ensure the non-dto properties on the context object (i.e. props
243
+ // ~~ensure the non-dto properties on the context object (i.e. props
228
244
  // that are not ib, gib, data, or rel8ns) match the data in the
229
- // context object
245
+ // context object~~ NO. THIS WILL BE IN A SEPARATE FUNCTION.
246
+ // See `validateContextDomainPayloadIbGibs`
230
247
 
231
- throw new Error(`not implemented (E: cb639658e1183fa6c8a4ebca023ba926)`);
248
+ // throw new Error(`not implemented (E: cb639658e1183fa6c8a4ebca023ba926)`);
249
+
250
+ console.error(`${lc} NAG ERROR MSG (NOT THROWN): not fully implemented yet (E: d574d85cb578637648ed403857f7a826)`);
251
+ return [];
232
252
  } catch (error) {
233
253
  console.error(`${lc} ${extractErrorMsg(error)}`);
234
254
  throw error;
@@ -239,7 +259,9 @@ export async function validateContextAndSagaFrame({ context }: { context: SyncSa
239
259
 
240
260
 
241
261
  /**
242
- * validates the payload ibgibs ({@link SyncSagaContextIbGib_V1.payloadIbGibsDomain}) intrinsically
262
+ * validates {@link SyncSagaContextIbGib_V1.payloadIbGibsDomain} intrinsically,
263
+ * and ensures that these payloadIbGibs also match the expected addrs in
264
+ * {@link SyncSagaContextData_V1}[{@link SYNC_SAGA_PAYLOAD_ADDRS_DOMAIN}].
243
265
  *
244
266
  * @returns empty array if valid, else validation errors
245
267
  */
@@ -248,6 +270,44 @@ export async function validateContextDomainPayloadIbGibs({ context }: { context:
248
270
  try {
249
271
  if (logalot) { console.log(`${lc} starting... (I: 9f9fe835bcc80c75aa7fd6d887fc0826)`); }
250
272
  console.error(`${lc} NAG MESSAGE (NOT THROWN). not implemented (E: bfe02ab36a227291a8f17ffc08f2ef26)`)
273
+ return [];
274
+ } catch (error) {
275
+ console.error(`${lc} ${extractErrorMsg(error)}`);
276
+ throw error;
277
+ } finally {
278
+ if (logalot) { console.log(`${lc} complete.`); }
279
+ }
280
+ }
281
+
282
+ /**
283
+ * move to sync-peer-helpers.mts as a pure function?
284
+ */
285
+ export async function authenticateContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
286
+ const lc = `[${authenticateContext.name}]`;
287
+ try {
288
+ if (logalot) { console.log(`${lc} starting... (I: 2677a482dfa873dcd1aa04a3031ff826)`); }
289
+
290
+ console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. // todo: authenticate (v1 must have this after we get merge logic workflow going) (E: bc3a78f2dab18ab64c36d055a4b50526)`);
291
+
292
+ return [];
293
+ } catch (error) {
294
+ console.error(`${lc} ${extractErrorMsg(error)}`);
295
+ throw error;
296
+ } finally {
297
+ if (logalot) { console.log(`${lc} complete.`); }
298
+ }
299
+ }
300
+
301
+ /**
302
+ * move to sync-peer-helpers.mts as a pure function?
303
+ */
304
+ export async function authorizeContext({ context }: { context: SyncSagaContextIbGib_V1 }): Promise<string[]> {
305
+ const lc = `[${authorizeContext.name}]`;
306
+ try {
307
+ if (logalot) { console.log(`${lc} starting... (I: 48c918b41ceec0cd489ca3b8819e6826)`); }
308
+
309
+ console.error(`${lc} NAG ERROR (NOT THROWN): not implemented. authorize business logic (v1 must have this, but later when we are working on admin vs. student)(E: bc3a78f2dab18ab64c36d055a4b50526)`);
310
+
251
311
  return [];
252
312
  } catch (error) {
253
313
  console.error(`${lc} ${extractErrorMsg(error)}`);
@@ -11,6 +11,10 @@ import { SYNC_SAGA_CONTEXT_ATOM } from './sync-saga-context-constants.mjs';
11
11
 
12
12
  export interface SyncSagaContextIb_V1 {
13
13
  atom: typeof SYNC_SAGA_CONTEXT_ATOM;
14
+ /**
15
+ * sagaFrame.data.n value
16
+ */
17
+ sagaN: number;
14
18
  /**
15
19
  * simple metadata count of data["@payloadAddrsDomain"]
16
20
  */
@@ -21,6 +25,10 @@ export interface SyncSagaContextIb_V1 {
21
25
  * Data payload for the Sync Saga Context.
22
26
  */
23
27
  export interface SyncSagaContextData_V1 extends IbGibData_V1 {
28
+ /**
29
+ * context's sagaFrame.data.n value
30
+ */
31
+ sagaN: number;
24
32
  /**
25
33
  * Payload data addresses for DOMAIN ibGibs (Timeline frames, user content).
26
34
  * Soft-linked via data property to avoid hard-linking graph dependencies.
@@ -35,7 +43,7 @@ export interface SyncSagaContextData_V1 extends IbGibData_V1 {
35
43
  export interface SyncSagaContextRel8ns_V1 extends IbGibRel8ns_V1 {
36
44
  /**
37
45
  * The primary Saga Frame being transported (Init, Ack, Delta, etc.).
38
- *
46
+ *
39
47
  * Should be a single addr.
40
48
  */
41
49
  sagaFrame: IbGibAddr[];
@@ -43,9 +51,9 @@ export interface SyncSagaContextRel8ns_V1 extends IbGibRel8ns_V1 {
43
51
  /**
44
52
  * The Ephemeral Session Keystone Identity used for this saga.
45
53
  * Required for validating the saga frame signature.
46
- *
54
+ *
47
55
  * ## notes
48
- *
56
+ *
49
57
  * This will be different for the sender and receiver, yes? hmm...
50
58
  * I think I need to put "sender" or "receiver" in the session keystone ib.
51
59
  */
@@ -59,7 +67,7 @@ export interface SyncSagaContextRel8ns_V1 extends IbGibRel8ns_V1 {
59
67
  export interface SyncSagaContextIbGib_V1 extends IbGib_V1<SyncSagaContextData_V1, SyncSagaContextRel8ns_V1> {
60
68
  /**
61
69
  * Domain ibgibs - OUTBOUND only.
62
- *
70
+ *
63
71
  * For inbound, the domain payload ibgibs are streamed via observable in the
64
72
  * peer.
65
73
  */
@@ -67,7 +75,7 @@ export interface SyncSagaContextIbGib_V1 extends IbGib_V1<SyncSagaContextData_V1
67
75
 
68
76
  /**
69
77
  * Reference to the actual sync saga frame that this context conveys.
70
- *
78
+ *
71
79
  * This frame's addr should be {@link SyncSagaContextRel8ns_V1.sagaFrame}.
72
80
  */
73
81
  sagaFrame: SyncIbGib_V1;