// /** // * This facade provides a simplified, timeline-oriented API for interacting // * with ibGibs, abstracting away low-level transform details (like nCounter, dna, // * dna, tjp rel8ns) and handling concurrency control (via locking) // * for maintaining timeline integrity. // */ // import { extractErrorMsg, getTimestampInTicks } from "@ibgib/helper-gib/dist/helpers/utils-helper.mjs"; // import { IbGib_V1, IbGibData_V1, Rel8n } from "@ibgib/ts-gib/dist/V1/types.mjs"; // import { IbGibAddr, TransformOpts_Mut8, TransformResult } from "@ibgib/ts-gib/dist/types.mjs"; // import { getIbGibAddr } from "@ibgib/ts-gib/dist/helper.mjs"; // import { rel8 } from "@ibgib/ts-gib/dist/V1/transforms/rel8.mjs"; // import { getGibInfo, isPrimitive } from "@ibgib/ts-gib/dist/V1/transforms/transform-helper.mjs"; // import { MetaspaceService } from "@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs"; // import { IbGibSpaceAny } from "@ibgib/core-gib/dist/witness/space/space-base-v1.mjs"; // import { SpecialIbGibType } from "@ibgib/core-gib/dist/common/other/other-types.mjs"; // import { // type setConfigAddr, type rel8ToSpecialIbGib, execInSpaceWithLocking, // persistTransformResult, // } from "@ibgib/core-gib/dist/witness/space/space-helper.mjs"; // import { GLOBAL_LOG_A_LOT } from "../../constants.mjs"; // import { mut8 } from "@ibgib/ts-gib/dist/V1/transforms/mut8.mjs"; // import { getSpecialConfigKey, toDto } from "@ibgib/core-gib/dist/common/other/ibgib-helper.mjs"; // const logalot = GLOBAL_LOG_A_LOT; // export interface Rel8nInfo { // rel8nName: string; // ibGibs: IbGib_V1[]; // } // export interface CommonTimelineOptsSansSkipLock { // /** // * space of spaces. Should be a singleton. @see {@link MetaspaceService} // */ // metaspace: MetaspaceService, // /** // * the space that contains both the {@link timeline} and ibGibs contained in // * {@link rel8nInfos}. // * // * if falsy, then the default local user space will be gotten from the // * {@link metaspace}. // */ // space?: IbGibSpaceAny, // } // export interface CommonTimelineOpts extends CommonTimelineOptsSansSkipLock { // /** // * if true, will not lock the timeline. ONLY use this if you know what you // * are doing, otherwise divergent timelines can occur. // * // * Really at that point, you may consider using the raw transforms // * themselves. // */ // skipLock?: boolean, // } // /** // * Deterministically generates a lock scope for a given timeline. // * // * ## internal details, may change // * // * ATOW (05/2025), this will return the tjpGib of the timeline. So if the addr // * is `comment Foo^ABC123.DEF456`, where ABC123 and DEF456 are hashes, then this // * will return `DEF456`. For an addr that is just `comment Bar^GHI789`, then // * this *is* the TJP and thus its gib is `GHI789` and that is what is returned. // */ // export async function getLockScope({ timeline }: { timeline: IbGib_V1 }): Promise { // const lc = `[${getLockScope.name}]`; // try { // if (logalot) { console.log(`${lc} starting...`); } // if (isPrimitive({ ibGib: timeline })) { // // this is an abnormal/unusual path // console.warn(`${lc} getting lock scope on a primitive ibgib can grossly impact performance. (W: 55203e415ae2ac7ddb19c21772b28925)`) // return getIbGibAddr({ ibGib: timeline }); // } else { // // happy path // const gibInfo = getGibInfo({ gib: timeline.gib }); // const tjpGib = gibInfo.tjpGib ?? gibInfo.punctiliarHash; // if (!tjpGib) { // // This should not happen for a valid ibGib, but as a safeguard // throw new Error(`${lc} (UNEXPECTED) Could not determine tjpGib or punctiliarHash from ibGib. (E: eb3b6472e9b335991a1b0869f772f7d3)`); // } // return tjpGib; // } // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // export async function isSameTimeline({ // a, // b, // }: { // a: IbGib_V1, // b: IbGib_V1, // }): Promise { // const lc = `[${isSameTimeline.name}]`; // try { // if (logalot) { console.log(`${lc} starting... (I: 0f8b68106f48a5c5c8d67f58b4b4d825)`); } // // DRY kluge b/c I'm soooooooo tired ...need to gtfo here // const aLockScope = await getLockScope({ timeline: a }); // const bLockScope = await getLockScope({ timeline: b }); // return aLockScope === bLockScope; // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // /** // * Appends a list of ibGibs to a timeline in the order given using the // * associated rel8nName (named edge). // * // * ## regarding persistence and registerNewIbGib pubsub // * // * The caller is responsible for persisting any ibGibs that are contained in // * {@link rel8nInfos}. However, all newly created ibgibs resulting from extending // * {@link timeline} *WILL* be saved in the {@link space}. // * // * This also will call `metaspace.registerNewIbGib` for the new timeline ibgib // * created ONLY, and will only do this AFTER both... // * * the timeline's lock is released AND AFTER // * * any indexes are updated if given via {@link timelineIndexInfo}. // * * atow (05/2025) this does not await the registerNewIbGib call, but this may // * change at any time. // */ // export async function appendToTimeline({ // timeline, // rel8nInfos, // timelineIndexInfo, // metaspace, // space, // skipLock, // }: { // timeline: IbGib_V1, // /** // * rel8nName/ibGibs pairings to append to the timeline. // */ // rel8nInfos: Rel8nInfo[], // /** // * If provided, will automatically update the index associated with the // * given {@link type} AFTER the timeline is extended but BEFORE the // * timeline's new ibgib is published via the {@link registerNewIbGib} // * function on {@link metaspace}. // * // * NOTE that this WILL LOCK the special ibgib index unless {@link skipLock} // * is true. // * // * @see {@link updateSpecialIndex} // */ // timelineIndexInfo?: { // type: SpecialIbGibType, // rel8nName: string, // }, // } & CommonTimelineOpts): Promise { // const lc = `[${appendToTimeline.name}]`; // try { // if (logalot) { console.log(`${lc} starting... (I: fcdff10832215068019355265f4cbc25)`); } // space ??= await metaspace.getLocalUserSpace({ lock: false }); // if (!space) { throw new Error(`(UNEXPECTED) space falsy? couldn't even get default local user space? (E: 2051b44a052d6a2984b9a22f680e4625)`); } // const lockScope = await getLockScope({ timeline }); // /** // * This fn actually does the append and will be executed in the locked // * setting if skipLock is falsy. // */ // const fn: () => Promise = async () => { // if (!space) { throw new Error(`(UNEXPECTED) space falsy? couldn't even get default local user space? (E: 845c4181c8c15d7219166ceb3c4dca25)`); } // // Get the latest version of the provided timeline ibgib. // const timelineAddr = getIbGibAddr({ ibGib: timeline }); // const latestTimelineIbGibAddr = await metaspace.getLatestAddr({ // addr: timelineAddr, // space, // }); // if (!latestTimelineIbGibAddr) { // throw new Error(`${lc} (UNEXPECTED) Could not get latest address for timeline ${getIbGibAddr({ ibGib: timeline })}. (E: a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9)`); // } // let latestTimelineIbGibDto: IbGib_V1 = toDto({ ibGib: timeline }); // if (timelineAddr !== latestTimelineIbGibAddr) { // const resGetLatest = await metaspace.get({ // addrs: [latestTimelineIbGibAddr], // space, // }); // if (resGetLatest.errorMsg || (resGetLatest.ibGibs ?? []).length !== 1) { // throw new Error(`${lc} (UNEXPECTED) couldn't get latest timeline ibgib (${latestTimelineIbGibAddr}) from space (${space.ib}). errorMsg: ${resGetLatest.errorMsg ?? '[unknown error]'} (E: b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0)`); // } // latestTimelineIbGibDto = resGetLatest.ibGibs!.at(0)!; // } // // Prepare rel8nsToAddByAddr // const rel8nsToAddByAddr: { [name: string]: IbGibAddr[] } = {}; // // Add the 'past' rel8n pointing to the previous timeline frame. // // rel8nsToAddByAddr.past = [getIbGibAddr({ ibGib: latestTimelineIbGib })]; // this happens automatically // // Add rel8ns from the provided rel8nInfos. // for (const rel8nInfo of rel8nInfos) { // const { rel8nName, ibGibs } = rel8nInfo; // if (ibGibs.length === 0) { // console.warn(`${lc} tried to add 0 ibGibs to rel8nName ${rel8nName}? skipping... (W: 708252dfdeb60757fee4554e769aaa25)`); // continue; // } // if (!rel8nsToAddByAddr[rel8nName]) { rel8nsToAddByAddr[rel8nName] = []; } // rel8nsToAddByAddr[rel8nName].push(...ibGibs.map(ibGib => getIbGibAddr({ ibGib }))); // } // // Perform a rel8 transform on the latest timeline ibgib. // const resRel8 = await rel8({ // type: 'rel8', // assuming rel8 is the transform type // src: latestTimelineIbGibDto, // Use the latest as the source // rel8nsToAddByAddr, // dna: true, // nCounter: true, // }); // const newTimelineIbGib = resRel8.newIbGib; // // Persist the transform result. // await metaspace.persistTransformResult({ resTransform: resRel8, space }); // // If timelineIndexInfo is provided, update the special index. // if (timelineIndexInfo) { // await updateSpecialIndex({ // type: timelineIndexInfo.type, // rel8nInfos: [{ rel8nName: timelineIndexInfo.rel8nName, ibGibs: [newTimelineIbGib] }], // metaspace, // space, // skipLock, // }); // } // // should we publish within the lock or not within the lock? // // should we await the publish or spin it off // // right now I have this spin off, inside the lock // // await metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // spin off // return newTimelineIbGib; // }; // const newTimelineIbGib = skipLock ? // await fn() : // await execInSpaceWithLocking({ // scope: lockScope, // secondsValid: 180, // Example timeout // maxDelayMs: 100, // Example delay // maxLockAttempts: 1800, // Example attempts // space, // callerInstanceId: getTimestampInTicks(), // fn, // }); // // should we publish within the lock or not within the lock? // // should we await the publish or spin it off // // right now I have this spin off, inside the lock // // await metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // // metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // spin off // return newTimelineIbGib; // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // /** // * Updates a special ibgib in the given {@link space} with new and/or updated // * {@link rel8nInfos}. // * // * ## on "special" ibgibs // * // * "Special" ibgibs are mostly used as indexes, but not necessarily. These are // * slightly different than most normal ibgibs in that they are not in some way // * or another attached to a root in the space, rather, they are rel8d directly // * to the local user space itself. So when a special ibgib is changed, i.e. its // * own timeline is extended, its new address is always proactively updated on // * the space directly. so `space.rel8ns[key]` (where key is derived from the // * given {@link type}) is updated with newSpecialIbGib's addr. // * // * @see {@link setConfigAddr} // * @see {@link rel8ToSpecialIbGib} // * // * ## upsert // * // * This is analogous to an upsert operation *into* the special index. So we are // * updating the index's rel8ns either way whether or not that rel8n already // * exists. // */ // export async function updateSpecialIndex({ // type, // rel8nInfos, // dataToAddOrPatch, // metaspace, // space, // skipLock, // }: { // /** // * identifying type of the special index. For example, spaces usually get // * initialized with a "tags" index. Individual tag ibgibs will be rel8d // * to this index using the `SpecialIbGibType.tags`, but really any string // * can be used as this type. // * // * For example, agents (atow 05/2025) have a soft type in their data. // * These agents are then indexed via this agent.data.type so that each type of // * agent has its own index, e.g., "primaryagent" or "renderable". // */ // type: SpecialIbGibType, // rel8nInfos?: Rel8nInfo[], // dataToAddOrPatch?: any, // } & CommonTimelineOpts): Promise { // const lc = `[${updateSpecialIndex.name}]`; // try { // if (logalot) { console.log(`${lc} starting... (I: 6e7d05fe916d813b71766e2eaa747c25)`); } // if (type === "latest") { throw new Error(`cannot update the "latest" special index by this function. The registerNewIbGib will do this automatically. (E: 231eb78a221ccdbcf56cd1899260a425)`); } // space ??= await metaspace.getLocalUserSpace({ lock: false }); // if (!space) { throw new Error(`(UNEXPECTED) space falsy? couldn't even get default local user space? (E: 43067821a4749a7648fe2612d25d7f25)`); } // /** // * This fn actually does the update and will be executed in the locked // * setting. // */ // const fn: () => Promise = async () => { // const fnGetSpecialIndex = async () => { // // always get the latest version of the special index ibgib // // fresh. The initialize: true option will create it if it // // doesn't exist. // const specialIndex = await metaspace.getSpecialIbGib({ // type, // space, // initialize: true, // }); // if (!specialIndex) { // throw new Error(`(UNEXPECTED) couldn't initialize/get special ibgib index of type ${type}. (E: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6)`); // } // if (!specialIndex.rel8ns) { // console.warn(`${lc} not sure if this ever hits, but is there ever a scenario where specialIndex.rel8ns is falsy? (W: 06161c366bc7ec858b9b5aa7ee9b6d25)`) // } // return specialIndex; // } // for (const rel8nInfo of (rel8nInfos ?? [])) { // // parse the rel8nInfo for this iteration // const { rel8nName, ibGibs } = rel8nInfo; // if (ibGibs.length === 0) { // console.error(`${lc} ibGibs empty. skipping rel8nName (${rel8nName}). (E: 150d74f73f97aea1b97d173d92c77125)`); // } // const specialIndex = await fnGetSpecialIndex(); // // // always get the latest version of the special index ibgib // // // fresh. The initialize: true option will create it if it // // // doesn't exist. // // const specialIndex = await metaspace.getSpecialIbGib({ // // type, // // space, // // initialize: true, // // }); // // if (!specialIndex) { // // throw new Error(`(UNEXPECTED) couldn't initialize/get special ibgib index of type ${type}. (E: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6)`); // // } // // if (!specialIndex.rel8ns) { // // console.warn(`${lc} not sure if this ever hits, but is there ever a scenario where specialIndex.rel8ns is falsy? (W: 06161c366bc7ec858b9b5aa7ee9b6d25)`) // // } // const existingSpecialIndexRel8ns = specialIndex.rel8ns ?? {}; // // before we just add all the ibgibs, we need to gather info on // // what previous ibgibs we need to unrel8 // let addrsToUnRel8: undefined | IbGibAddr[] = undefined; // // check if we even need to even compare existing rel8ns // const existingAddrsThisRel8nName = existingSpecialIndexRel8ns[rel8nName] ?? []; // if (existingAddrsThisRel8nName.length > 0) { // // we have existing rel8ns for this rel8nName, so remove any // // that share the tjpGib of addrs we're adding or use the // // past/current full addrs. check actual code here for impl // const toUnrel8ThisRel8nName_Set: Set = new Set(); // ibGibs.forEach(ibGib => { // const addr = getIbGibAddr({ ibGib }); // // by tjpGib impl // // const gibInfo = getGibInfo({ gib: ibGib.gib }); // // const tjpGib = gibInfo.tjpGib ?? gibInfo.punctiliarHash ?? ibGib.gib ?? GIB; // // existingAddrsThisRel8nName // // .filter(x => x.includes(tjpGib)) // // .forEach(x => toUnrel8ThisRel8nName_Set.add(x)); // // by full addrs impl // const pastAddrs = ibGib.rel8ns?.past ?? []; // existingAddrsThisRel8nName // .filter(x => [...pastAddrs, addr].includes(x)) // .forEach(x => toUnrel8ThisRel8nName_Set.add(x)); // }); // if (toUnrel8ThisRel8nName_Set.size > 0) { // addrsToUnRel8 = Array.from(toUnrel8ThisRel8nName_Set); // } // } // // we now have enough to execute the rel8 // await metaspace.rel8ToSpecialIbGib({ // type, // rel8nName, // ibGibsToRel8: ibGibs, // addrsToUnRel8, // space, // linked: false, // severPast: false, // deletePreviousSpecialIbGib: false, // only used in latest special ibgib // }) // } // if (Object.keys(dataToAddOrPatch ?? {}).length > 0) { // const specialIndex = await fnGetSpecialIndex(); // const resNewSpecial = await mut8({ // src: specialIndex, // dataToAddOrPatch, // dna: false, // linkedRel8ns: [Rel8n.past], // nCounter: true, // }); // const newSpecialIbGib = resNewSpecial.newIbGib; // // persist // await persistTransformResult({ resTransform: resNewSpecial, space: space! }); // // update the space ibgib which contains the special/config information // const configKey = getSpecialConfigKey({ type }); // await metaspace.setConfigAddr({ // key: configKey, // addr: getIbGibAddr({ ibGib: newSpecialIbGib }), // space, // }); // await metaspace.registerNewIbGib({ ibGib: newSpecialIbGib, space, }); // } // } // if (skipLock) { // await fn(); // } else { // // Use execInSpaceWithLocking with the special index type as the scope. // // We are currently choosing to always lock for special indexes for // // safety. The skipLock parameter from CommonTimelineOpts is included // // in the signature for consistency but not used in the locking logic // // here based on our decision to always lock special indexes. // await execInSpaceWithLocking({ // scope: type, // Use the special index type as the lock scope. // secondsValid: 60, // Example timeout // maxDelayMs: 100, // Example delay // maxLockAttempts: 600, // Example attempts // space, // // callerInstanceId: // You might need a way to generate a unique ID for the caller // fn, // }); // } // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // export async function getLatestTimelineIbGibDto_nonLocking({ // timeline, // timelineAddr, // metaspace, // space, // }: { // timeline?: TIbGib, // timelineAddr?: IbGibAddr, // metaspace: MetaspaceService, // space: IbGibSpaceAny, // }): Promise { // const lc = `[${getLatestTimelineIbGibDto_nonLocking.name}]`; // try { // if (logalot) { console.log(`${lc} starting... (I: f2b605361368e1956f6db878dbfeb825)`); } // if (!timeline && !timelineAddr) { throw new Error(`either timeline or timelineAddr required. (E: 97551b2b18ecd22a18185a783f9a0825)`); } // timelineAddr ??= getIbGibAddr({ ibGib: timeline }); // // const timelineAddr = getIbGibAddr({ ibGib: timeline }); // const latestTimelineIbGibAddr = await metaspace.getLatestAddr({ // addr: timelineAddr, // space, // }) ?? timelineAddr; // if (!latestTimelineIbGibAddr) { // throw new Error(`${lc} (UNEXPECTED) Could not get latest address for timeline ${getIbGibAddr({ ibGib: timeline })}. (E: a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9)`); // } // let latestTimelineIbGibDto: TIbGib;// = toDto({ ibGib: timeline }) as TIbGib; // if (timelineAddr === latestTimelineIbGibAddr) { // // latest addr is the same // if (!timeline) { // const resGetLatest = await metaspace.get({ // addrs: [latestTimelineIbGibAddr], // space, // }); // if (resGetLatest.errorMsg || (resGetLatest.ibGibs ?? []).length !== 1) { // throw new Error(`${lc} (UNEXPECTED) couldn't get latest timeline ibgib (${latestTimelineIbGibAddr}) from space (${space.ib}). errorMsg: ${resGetLatest.errorMsg ?? '[unknown error]'} (E: 3fc767a594788a43a4ba18c87491a825)`); // } // timeline = resGetLatest.ibGibs!.at(0)! as TIbGib; // } // latestTimelineIbGibDto = toDto({ ibGib: timeline }) as TIbGib; // } else { // // latest addr is different // const resGetLatest = await metaspace.get({ // addrs: [latestTimelineIbGibAddr], // space, // }); // if (resGetLatest.errorMsg || (resGetLatest.ibGibs ?? []).length !== 1) { // throw new Error(`${lc} (UNEXPECTED) couldn't get latest timeline ibgib (${latestTimelineIbGibAddr}) from space (${space.ib}). errorMsg: ${resGetLatest.errorMsg ?? '[unknown error]'} (E: b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0)`); // } // latestTimelineIbGibDto = resGetLatest.ibGibs!.at(0)! as TIbGib; // } // return latestTimelineIbGibDto; // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // export async function mut8Timeline({ // timeline, // timelineAddr, // mut8Opts, // metaspace, // space, // skipLock, // timelineIndexInfo, // }: { // /** // * timeline ibgib whose `data` we're mutating. // */ // timeline?: IbGib_V1, // timelineAddr?: IbGibAddr, // /** // * 'dataToRename' | 'dataToRemove' | 'dataToAddOrPatch' | 'mut8Ib' // * // * The rest of the mut8 options are automatic in this simplified timeline // * api. // */ // mut8Opts: Pick>, 'dataToRename' | 'dataToRemove' | 'dataToAddOrPatch' | 'mut8Ib'>, // /** // * If provided, will automatically update the index associated with the // * given {@link type} AFTER the timeline is extended but BEFORE the // * timeline's new ibgib is published via the {@link registerNewIbGib} // * function on {@link metaspace}. // * // * NOTE that this WILL LOCK the special ibgib index unless {@link skipLock} // * is true. // * // * @see {@link updateSpecialIndex} // */ // timelineIndexInfo?: { // type: SpecialIbGibType, // rel8nName: string, // }, // } & CommonTimelineOpts): Promise> { // const lc = `[${mut8Timeline.name}]`; // try { // if (logalot) { console.log(`${lc} starting... (I: genuuid)`); } // if (!timeline && !timelineAddr) { throw new Error(`(UNEXPECTED) both timeline and timelineAddr falsy? either one is required. (E: a19d98c6acb87af3b876c1484f6ac825)`); } // space ??= await metaspace.getLocalUserSpace({ lock: false }); // if (!space) { throw new Error(`(UNEXPECTED) space falsy? couldn't even get default local user space? (E: genuuid)`); } // if (!timeline) { // const resGet = await metaspace.get({ // addrs: [timelineAddr!], // space, // }); // if (!resGet.success || resGet.ibGibs?.length !== 1) { // throw new Error(`couldn't get timeline ibGib from timelineAddr (${timelineAddr!}) in space (${space?.ib ?? 'undefined'}) (E: genuuid)`); // } // timeline = resGet.ibGibs.at(0)! as IbGib_V1; // } // const lockScope = await getLockScope({ timeline }); // /** // * This fn actually does the update and will be executed in the locked // * setting. // */ // const fn: () => Promise> = async () => { // if (!space) { throw new Error(`(UNEXPECTED) space falsy? couldn't even get default local user space? (E: 845c4181c8c15d7219166ceb3c4dca25)`); } // // Get the latest version of the provided timeline ibgib. // if (!timeline) { throw new Error(`(UNEXPECTED) timeline falsy? we should be ensured that it's truthy at this point. (E: 2e1758b2cc3820531f7ac7f5f6b3a825)`); } // const latestTimelineIbGibDto = await getLatestTimelineIbGibDto_nonLocking({ // timeline, metaspace, space, // }); // // adjust mut8Opts depending // const resMut8 = await mut8({ // ...mut8Opts, // src: latestTimelineIbGibDto, // dna: true, // nCounter: true, // }) as TransformResult>; // const newTimelineIbGib = resMut8.newIbGib; // // Persist the transform result. // await metaspace.persistTransformResult({ resTransform: resMut8, space }); // // If timelineIndexInfo is provided, update the special index. // if (timelineIndexInfo) { // await updateSpecialIndex({ // type: timelineIndexInfo.type, // rel8nInfos: [{ rel8nName: timelineIndexInfo.rel8nName, ibGibs: [newTimelineIbGib] }], // metaspace, // space, // skipLock, // }); // } // // should we publish within the lock or not within the lock? // // should we await the publish or spin it off // // right now I have this spin off, inside the lock // // await metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // // we await the register call because this spins off the publish events (we are assuming implementation details here) // await metaspace.registerNewIbGib({ ibGib: newTimelineIbGib, space }); // already spins off // return newTimelineIbGib; // } // const newTimelineIbGib = skipLock ? // await fn() : // await execInSpaceWithLocking({ // scope: lockScope, // secondsValid: 180, // Example timeout // maxDelayMs: 100, // Example delay // maxLockAttempts: 1800, // Example attempts // space, // callerInstanceId: getTimestampInTicks(), // fn, // }); // return newTimelineIbGib; // } catch (error) { // console.error(`${lc} ${extractErrorMsg(error)}`); // throw error; // } finally { // if (logalot) { console.log(`${lc} complete.`); } // } // } // // todo: implement simplified locking wrappers to raw `rel8`, and `fork` // // transforms functions. These should be `rel8Timeline`, and `forkTimeline`. But // // these should not have skipLock available, since at that point you're really // // basically doing the raw transforms and can use those.