@voltro/plugin-rooms 0.0.0-stage → 0.87.0
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.
- package/CHANGELOG.md +24329 -0
- package/LICENSE +61 -0
- package/README.md +9204 -2
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +11322 -0
- package/dist/actor.js +1474 -0
- package/dist/apiBinding.js +678 -0
- package/dist/apiRegistryBinding.js +399 -0
- package/dist/apiReservations.js +433 -0
- package/dist/baselines.js +73 -0
- package/dist/bots.d.ts +1485 -0
- package/dist/bots.js +563 -0
- package/dist/catalog.js +80 -0
- package/dist/checkpointJson.js +24 -0
- package/dist/checkpointStore.js +386 -0
- package/dist/client.js +56 -0
- package/dist/clockSync.js +51 -0
- package/dist/collision.js +156 -0
- package/dist/commandDelivery.js +101 -0
- package/dist/commandRecord.js +11 -0
- package/dist/commandWithdrawal.js +183 -0
- package/dist/connection.js +497 -0
- package/dist/controlCarrier.js +375 -0
- package/dist/controlRegistry.js +79 -0
- package/dist/controlTarget.js +45 -0
- package/dist/controlTransport.js +574 -0
- package/dist/developmentBinding.js +113 -0
- package/dist/directory.js +323 -0
- package/dist/directoryProjection.js +117 -0
- package/dist/errors.d.ts +125 -0
- package/dist/errors.js +53 -0
- package/dist/fixed.d.ts +284 -0
- package/dist/fixed.js +10 -0
- package/dist/fixed32.js +134 -0
- package/dist/fixedCollision.js +60 -0
- package/dist/fixedCollision32.js +109 -0
- package/dist/fixedMath.js +56 -0
- package/dist/fixedRaw.js +11 -0
- package/dist/fixedSlabs.js +34 -0
- package/dist/fixedTrig.js +48 -0
- package/dist/fixedTrig32.js +38 -0
- package/dist/fixedVectors.js +113 -0
- package/dist/fixedVectors32.js +95 -0
- package/dist/fixedWide.js +50 -0
- package/dist/fixedWords.js +46 -0
- package/dist/gateway.js +57 -0
- package/dist/geometry-retention-app/rooms.geometryJournalRetention.workflow.server.tsx +4 -0
- package/dist/geometry-retention-app/rooms.geometryJournalRetention.workflow.tsx +14 -0
- package/dist/geometry-worker/worker.d.mts +2 -0
- package/dist/geometry-worker/worker.mjs +50 -0
- package/dist/geometry.d.ts +2249 -0
- package/dist/geometry.js +40 -0
- package/dist/geometryActivation.js +82 -0
- package/dist/geometryActorInventory.js +108 -0
- package/dist/geometryAdminClient.js +87 -0
- package/dist/geometryAdminData.js +32 -0
- package/dist/geometryAdminFixtures.js +50 -0
- package/dist/geometryAdminPorts.js +5 -0
- package/dist/geometryAdminRpc.js +58 -0
- package/dist/geometryAdminRpcRoutes.js +49 -0
- package/dist/geometryAdminSchemas.js +39 -0
- package/dist/geometryAdministration.js +190 -0
- package/dist/geometryAdministrationPorts.js +5 -0
- package/dist/geometryApiBinding.js +165 -0
- package/dist/geometryAppStorage.js +58 -0
- package/dist/geometryArtifacts.js +198 -0
- package/dist/geometryAssetBundle.js +117 -0
- package/dist/geometryAssetClient.js +25 -0
- package/dist/geometryAssetData.js +106 -0
- package/dist/geometryAssetHttp.js +123 -0
- package/dist/geometryAssetPorts.js +5 -0
- package/dist/geometryAssetRpc.js +30 -0
- package/dist/geometryAssetRpcRoutes.js +40 -0
- package/dist/geometryAssetStorageGrant.js +103 -0
- package/dist/geometryBoxOverlap.js +110 -0
- package/dist/geometryCatalogueDigest.js +111 -0
- package/dist/geometryCellCoverage.js +85 -0
- package/dist/geometryCellLoader.js +28 -0
- package/dist/geometryChannel.js +134 -0
- package/dist/geometryChunkHttp.js +54 -0
- package/dist/geometryChunkLeases.js +22 -0
- package/dist/geometryClient.d.ts +1429 -0
- package/dist/geometryClient.js +149 -0
- package/dist/geometryClientChunks.js +330 -0
- package/dist/geometryClientDelta.js +25 -0
- package/dist/geometryClientHttp.js +37 -0
- package/dist/geometryClientInterest.js +109 -0
- package/dist/geometryClientStatic.js +34 -0
- package/dist/geometryCms.d.ts +763 -0
- package/dist/geometryCms.js +217 -0
- package/dist/geometryCommitCoordinator.js +241 -0
- package/dist/geometryCompactionFixture.js +84 -0
- package/dist/geometryCompactionStrategies.js +38 -0
- package/dist/geometryConnectionClient.js +23 -0
- package/dist/geometryDerivationFixtures.js +141 -0
- package/dist/geometryDerivationStrategies.js +27 -0
- package/dist/geometryDigest.js +13 -0
- package/dist/geometryEditChannel.js +70 -0
- package/dist/geometryEditIngress.js +263 -0
- package/dist/geometryEdits.js +366 -0
- package/dist/geometryEnvelope.js +41 -0
- package/dist/geometryGridRaycast.js +92 -0
- package/dist/geometryGridSweep.js +92 -0
- package/dist/geometryHeightfield.js +166 -0
- package/dist/geometryHeightfieldRaycast.js +74 -0
- package/dist/geometryHeightfieldSweep.js +85 -0
- package/dist/geometryHeightfieldVolume.js +45 -0
- package/dist/geometryHost.js +322 -0
- package/dist/geometryHostDirectory.js +207 -0
- package/dist/geometryHostMutations.js +137 -0
- package/dist/geometryHostStreams.js +124 -0
- package/dist/geometryHttpBody.js +76 -0
- package/dist/geometryHttpRoutes.js +112 -0
- package/dist/geometryImportGltf.js +300 -0
- package/dist/geometryImportLdtk.js +54 -0
- package/dist/geometryImportPng.js +144 -0
- package/dist/geometryImportPublication.js +67 -0
- package/dist/geometryImportTiled.js +39 -0
- package/dist/geometryImportTiles.js +136 -0
- package/dist/geometryImportVox.js +130 -0
- package/dist/geometryImportedSource.js +101 -0
- package/dist/geometryInspectEndpoint.js +248 -0
- package/dist/geometryInspection.js +92 -0
- package/dist/geometryInstall.js +121 -0
- package/dist/geometryJournalArchiveData.js +21 -0
- package/dist/geometryJournalArchiveIndex.js +330 -0
- package/dist/geometryJournalArchiveTable.js +21 -0
- package/dist/geometryJournalCompaction.js +100 -0
- package/dist/geometryJournalPatch.js +47 -0
- package/dist/geometryJournalRetention.js +112 -0
- package/dist/geometryJournalRetentionSchemas.js +36 -0
- package/dist/geometryJournalRetentionSweep.js +112 -0
- package/dist/geometryJournalRetentionWorkflow.js +28 -0
- package/dist/geometryJournalRetentionWorkflowData.js +31 -0
- package/dist/geometryJournalStorage.js +148 -0
- package/dist/geometryLoader.js +118 -0
- package/dist/geometryManifest.js +113 -0
- package/dist/geometryManifestChannel.js +93 -0
- package/dist/geometryManifestClient.js +122 -0
- package/dist/geometryManifestData.js +49 -0
- package/dist/geometryManifestPorts.js +5 -0
- package/dist/geometryManifestPublication.js +109 -0
- package/dist/geometryManifestSource.js +68 -0
- package/dist/geometryMigrationJournal.js +14 -0
- package/dist/geometryMigrationStrategies.js +7 -0
- package/dist/geometryMigrations.js +323 -0
- package/dist/geometryNativeMetadata.js +52 -0
- package/dist/geometryPatch.js +170 -0
- package/dist/geometryPersistence.js +449 -0
- package/dist/geometryPersistenceCapture.js +69 -0
- package/dist/geometryPersistenceData.js +140 -0
- package/dist/geometryPersistencePorts.js +5 -0
- package/dist/geometryPlayerAdmission.js +34 -0
- package/dist/geometryPlayerEditOwner.js +265 -0
- package/dist/geometryPlayerEdits.js +49 -0
- package/dist/geometryPrepared.js +188 -0
- package/dist/geometryPrivacyFence.js +24 -0
- package/dist/geometryProceduralPublication.js +91 -0
- package/dist/geometryProceduralWorker.js +164 -0
- package/dist/geometryPublication.js +110 -0
- package/dist/geometryRayAlgebra.js +116 -0
- package/dist/geometryReadClient.js +157 -0
- package/dist/geometryReadPorts.js +5 -0
- package/dist/geometryReadRpc.js +27 -0
- package/dist/geometryReadRpcRoutes.js +47 -0
- package/dist/geometryReliablePublication.js +82 -0
- package/dist/geometryReloadPorts.js +46 -0
- package/dist/geometryReloadSource.js +278 -0
- package/dist/geometryRenderCache.js +165 -0
- package/dist/geometryRenderLod.js +102 -0
- package/dist/geometryRollback.js +125 -0
- package/dist/geometryRollbackCoordinator.js +203 -0
- package/dist/geometryRollbackPorts.js +46 -0
- package/dist/geometryRollbackSource.js +209 -0
- package/dist/geometryRollbackStore.js +198 -0
- package/dist/geometrySchemas.js +27 -0
- package/dist/geometryServer.d.ts +2766 -0
- package/dist/geometryServer.js +62 -0
- package/dist/geometryShapeRaycast.js +111 -0
- package/dist/geometryShapeSegments.js +34 -0
- package/dist/geometryShapes.js +223 -0
- package/dist/geometrySnapshot.js +76 -0
- package/dist/geometrySnapshotChannel.js +160 -0
- package/dist/geometrySnapshotClient.js +159 -0
- package/dist/geometrySnapshotPreparation.js +76 -0
- package/dist/geometrySnapshotServer.js +191 -0
- package/dist/geometrySqlOwner.js +21 -0
- package/dist/geometryStorage.js +127 -0
- package/dist/geometryStorageGrant.js +69 -0
- package/dist/geometryStorageIdentity.js +9 -0
- package/dist/geometryTileArtifact.js +10 -0
- package/dist/geometryTileCodec.js +194 -0
- package/dist/geometryTileCollision.js +96 -0
- package/dist/geometryTileNavigation.js +128 -0
- package/dist/geometryTileView.js +35 -0
- package/dist/geometryVersionActivation.js +114 -0
- package/dist/geometryVersionClient.js +238 -0
- package/dist/geometryVersionCompare.js +40 -0
- package/dist/geometryVersionMigration.js +106 -0
- package/dist/geometryVoxel.js +253 -0
- package/dist/geometryWorldEntitySubject.js +32 -0
- package/dist/geometryWorldExtent.js +12 -0
- package/dist/geometryWorldMetadata.js +38 -0
- package/dist/geometryWorldStrategyFixtures.js +127 -0
- package/dist/geometryWorldView.js +307 -0
- package/dist/host.js +128 -0
- package/dist/hostBinding.js +277 -0
- package/dist/hostCellObservation.js +114 -0
- package/dist/hostClientCapacity.js +90 -0
- package/dist/hostCommandScope.js +64 -0
- package/dist/hostController.js +3094 -0
- package/dist/hostDeployment.js +65 -0
- package/dist/hostDrain.js +152 -0
- package/dist/hostDrainPorts.js +5 -0
- package/dist/hostDriver.js +179 -0
- package/dist/hostLane.js +288 -0
- package/dist/hostListener.js +79 -0
- package/dist/hostListenerBinding.js +19 -0
- package/dist/hostLoopObservation.js +90 -0
- package/dist/hostMetrics.js +56 -0
- package/dist/hostRegistryBinding.js +418 -0
- package/dist/hostSelection.js +16 -0
- package/dist/hostShutdown.js +47 -0
- package/dist/hostTurnObservation.js +53 -0
- package/dist/identities.js +4 -0
- package/dist/index.d.ts +8632 -0
- package/dist/index.js +232 -0
- package/dist/inputReceipts.js +63 -0
- package/dist/inputRedundancy.js +55 -0
- package/dist/inspect.js +238 -0
- package/dist/lockstep.d.ts +436 -0
- package/dist/lockstep.js +382 -0
- package/dist/lockstepAdmission.js +262 -0
- package/dist/lockstepAdmissionCodec.js +94 -0
- package/dist/lockstepAdmissionPorts.js +5 -0
- package/dist/lockstepClientSession.js +578 -0
- package/dist/lockstepDefinition.js +148 -0
- package/dist/lockstepHostLoop.js +243 -0
- package/dist/lockstepInitialAdmission.js +67 -0
- package/dist/lockstepInitialStrategyFixtures.js +45 -0
- package/dist/lockstepJournal.js +395 -0
- package/dist/lockstepJournalCodec.js +254 -0
- package/dist/lockstepJournalPorts.js +5 -0
- package/dist/lockstepJournalRebuild.js +208 -0
- package/dist/lockstepJournalRows.js +57 -0
- package/dist/lockstepMembers.js +131 -0
- package/dist/lockstepMessages.js +47 -0
- package/dist/lockstepOwnedRoom.js +764 -0
- package/dist/lockstepPolicies.js +84 -0
- package/dist/lockstepReact.js +47 -0
- package/dist/lockstepRecoveryTruth.js +121 -0
- package/dist/lockstepRosterConfig.js +32 -0
- package/dist/lockstepSeed.js +12 -0
- package/dist/lockstepSeedFixture.js +20 -0
- package/dist/lockstepServer.d.ts +3897 -0
- package/dist/lockstepServer.js +325 -0
- package/dist/lockstepServerConfig.js +101 -0
- package/dist/lockstepServerRoles.js +403 -0
- package/dist/lockstepServerStrategyFixtures.js +33 -0
- package/dist/lockstepStrategies.js +6 -0
- package/dist/lockstepStrategyFixtures.js +137 -0
- package/dist/lockstepTerminal.js +90 -0
- package/dist/lockstepTerminalPorts.js +5 -0
- package/dist/lockstepTransport.js +773 -0
- package/dist/lockstepTransportConfig.js +32 -0
- package/dist/lockstepWireRoster.js +34 -0
- package/dist/matchRoomProvider.js +32 -0
- package/dist/matchRooms.js +19 -0
- package/dist/membershipObserver.js +47 -0
- package/dist/moderation.js +98 -0
- package/dist/movementSpecials.js +104 -0
- package/dist/ownership.js +17 -0
- package/dist/ownershipWithdrawal.js +18 -0
- package/dist/pcg32.js +96 -0
- package/dist/ports.d.ts +1241 -0
- package/dist/ports.js +11 -0
- package/dist/quaternion.js +70 -0
- package/dist/react.d.ts +406 -0
- package/dist/react.js +109 -0
- package/dist/reaper-app/rooms.reaper.workflow.server.tsx +5 -0
- package/dist/reaper-app/rooms.reaper.workflow.tsx +13 -0
- package/dist/reaper.js +243 -0
- package/dist/reaperSchemas.js +42 -0
- package/dist/reaperWorkflow.js +70 -0
- package/dist/recovery.js +189 -0
- package/dist/recoverySeats.js +26 -0
- package/dist/replay.d.ts +273 -0
- package/dist/replay.js +485 -0
- package/dist/replayPorts.js +5 -0
- package/dist/replayRecording.js +67 -0
- package/dist/replaySchema.js +157 -0
- package/dist/replayStorage.d.ts +149 -0
- package/dist/replayStorage.js +485 -0
- package/dist/reservationBatch.js +422 -0
- package/dist/reservationSchemas.js +17 -0
- package/dist/reservations.js +259 -0
- package/dist/reservePort.js +69 -0
- package/dist/resolvedOptions.js +4 -0
- package/dist/room.d.ts +1006 -0
- package/dist/room.js +284 -0
- package/dist/roomAccessSweep.js +95 -0
- package/dist/roomAppCommandControl.js +59 -0
- package/dist/roomAuthoringStrategy.js +17 -0
- package/dist/roomErasure.js +198 -0
- package/dist/roomPoolRuntimeDefaults.js +24 -0
- package/dist/roomPoolSelection.js +19 -0
- package/dist/roomPoolTopology.js +212 -0
- package/dist/rpc.d.ts +551 -0
- package/dist/rpc.js +112 -0
- package/dist/rpcClient.js +152 -0
- package/dist/rpcRoutes.js +28 -0
- package/dist/runtime.js +1123 -0
- package/dist/schemaHistory.js +98 -0
- package/dist/seatStore.js +151 -0
- package/dist/seatStrategyFixtures.js +52 -0
- package/dist/seatSubject.js +32 -0
- package/dist/seats.js +130 -0
- package/dist/serverSession.js +811 -0
- package/dist/serverSessionConfig.js +43 -0
- package/dist/sessionAdmission.js +53 -0
- package/dist/sidecarAdmission.js +103 -0
- package/dist/sidecarConfig.js +116 -0
- package/dist/sidecarConfigPublication.js +64 -0
- package/dist/sidecarHostListener.js +208 -0
- package/dist/sidecarIpc.js +205 -0
- package/dist/sidecarPeer.js +310 -0
- package/dist/sidecarProcessPort.js +28 -0
- package/dist/sidecarRuntime.js +168 -0
- package/dist/sidecarSelection.js +142 -0
- package/dist/sidecarWire.js +178 -0
- package/dist/sidecarWrites.js +163 -0
- package/dist/simulation.d.ts +391 -0
- package/dist/simulation.js +282 -0
- package/dist/simulationAuthoring.js +29 -0
- package/dist/simulationBytes.js +27 -0
- package/dist/simulationConformance.js +305 -0
- package/dist/simulationInputHistoryCapture.js +35 -0
- package/dist/simulationInputHistoryWire.js +193 -0
- package/dist/simulationOptionsWire.js +78 -0
- package/dist/simulationRecoveryWire.js +134 -0
- package/dist/simulationReplay.js +127 -0
- package/dist/simulationSnapshotWire.js +112 -0
- package/dist/simulationState.js +178 -0
- package/dist/snapshotBlob.js +126 -0
- package/dist/snapshotBlobCleanup.js +93 -0
- package/dist/snapshotBlobIndex.js +38 -0
- package/dist/snapshotBudget.js +80 -0
- package/dist/snapshotChain.js +185 -0
- package/dist/snapshotErasure.js +172 -0
- package/dist/snapshotInspection.js +105 -0
- package/dist/snapshotSegmentBlobs.js +58 -0
- package/dist/snapshotUploads.js +166 -0
- package/dist/socketTransport.js +253 -0
- package/dist/spatial.js +104 -0
- package/dist/spectatorPolicy.js +26 -0
- package/dist/spectatorProducer.js +89 -0
- package/dist/startFailureCause.js +4 -0
- package/dist/stateCodec.js +658 -0
- package/dist/strategies.d.ts +210 -0
- package/dist/strategies.js +8 -0
- package/dist/strategiesServer.d.ts +286 -0
- package/dist/strategiesServer.js +11 -0
- package/dist/strategyFixtures.js +182 -0
- package/dist/streamFraming.js +122 -0
- package/dist/streamTransport.js +266 -0
- package/dist/subjectAdmission.js +50 -0
- package/dist/subjectPrivacy.js +281 -0
- package/dist/subjectPrivacyBinding.js +90 -0
- package/dist/systemManifest.js +182 -0
- package/dist/tables.js +159 -0
- package/dist/testHarness.js +89 -0
- package/dist/testing.d.ts +3684 -0
- package/dist/testing.js +221 -0
- package/dist/testingPorts.js +271 -0
- package/dist/testingServer.d.ts +4060 -0
- package/dist/testingServer.js +18 -0
- package/dist/transform.d.ts +692 -0
- package/dist/transform.js +217 -0
- package/dist/transform3d.js +118 -0
- package/dist/transformCollection.js +24 -0
- package/dist/transformCollection3d.js +24 -0
- package/dist/transformCollectionCore.js +156 -0
- package/dist/transformFrames.js +121 -0
- package/dist/transformPrediction3d.js +127 -0
- package/dist/transformRules.js +123 -0
- package/dist/transformSchemas.js +20 -0
- package/dist/transport.js +32 -0
- package/dist/transportAuthoring.js +29 -0
- package/dist/transportCleanup.js +22 -0
- package/dist/transportConformance.js +124 -0
- package/dist/transportConnector.js +82 -0
- package/dist/transportEndpoints.js +38 -0
- package/dist/transportsServer.d.ts +5515 -0
- package/dist/transportsServer.js +6 -0
- package/dist/viewProjection.js +16 -0
- package/dist/web.d.ts +2286 -0
- package/dist/web.js +518 -0
- package/dist/webTransportClient.js +173 -0
- package/dist/wire.d.ts +992 -0
- package/dist/wire.js +492 -0
- package/dist/withdrawalPort.js +28 -0
- package/dist/world.d.ts +1894 -0
- package/dist/world.js +333 -0
- package/dist/worldActorReceipts.js +48 -0
- package/dist/worldActorTransferSnapshot.js +14 -0
- package/dist/worldAdmissionPending.js +8 -0
- package/dist/worldBoundaryCoordinator.js +148 -0
- package/dist/worldCatalog.js +81 -0
- package/dist/worldCellAllocation.js +203 -0
- package/dist/worldCellDestination.js +68 -0
- package/dist/worldCells.js +489 -0
- package/dist/worldChange.js +32 -0
- package/dist/worldClient.js +664 -0
- package/dist/worldClientControl.js +141 -0
- package/dist/worldClientPendingInput.js +16 -0
- package/dist/worldClientRpc.js +133 -0
- package/dist/worldClientRpcRoutes.js +43 -0
- package/dist/worldClientSchemas.js +28 -0
- package/dist/worldCommands.js +140 -0
- package/dist/worldData.js +42 -0
- package/dist/worldDefaultBinding.js +377 -0
- package/dist/worldDefaultGroupAdmission.js +82 -0
- package/dist/worldDefaultGroupAppServices.js +31 -0
- package/dist/worldDefaultGroupCompensation.js +109 -0
- package/dist/worldDefaultGroupContinuation.js +96 -0
- package/dist/worldDefaultGroupControl.js +72 -0
- package/dist/worldDefaultGroupMembers.js +85 -0
- package/dist/worldDefaultGroups.js +21 -0
- package/dist/worldDefaultPending.js +79 -0
- package/dist/worldDefaultService.js +245 -0
- package/dist/worldEntities.js +2980 -0
- package/dist/worldEntityCodec.js +21 -0
- package/dist/worldEntityHandoffView.js +154 -0
- package/dist/worldGeometry.js +170 -0
- package/dist/worldGhostAdmission.js +65 -0
- package/dist/worldGhostDestination.js +118 -0
- package/dist/worldGhostGateway.js +132 -0
- package/dist/worldGhostHandshake.js +108 -0
- package/dist/worldGhostHost.js +42 -0
- package/dist/worldGhostIngress.js +132 -0
- package/dist/worldGhostNeighborhood.js +70 -0
- package/dist/worldGhostNeighbors.js +86 -0
- package/dist/worldGhostOutbound.js +110 -0
- package/dist/worldGhostPublisher.js +216 -0
- package/dist/worldGhostReceiver.js +213 -0
- package/dist/worldGhostSender.js +146 -0
- package/dist/worldGhostSocket.js +78 -0
- package/dist/worldGhostWire.js +172 -0
- package/dist/worldGroupCommand.js +49 -0
- package/dist/worldGroupDeadline.js +115 -0
- package/dist/worldGroupPreparation.js +115 -0
- package/dist/worldGroupReadyControl.js +128 -0
- package/dist/worldGroupSupervisor.js +120 -0
- package/dist/worldHandoffMetrics.js +59 -0
- package/dist/worldHandoffView.js +100 -0
- package/dist/worldHostSource.js +69 -0
- package/dist/worldInspectEndpoint.js +250 -0
- package/dist/worldInspection.js +109 -0
- package/dist/worldInstanceAdmission.js +31 -0
- package/dist/worldInstanceAllocation.js +116 -0
- package/dist/worldInstanceDestination.js +64 -0
- package/dist/worldInstanceExpiry.js +282 -0
- package/dist/worldInstanceExpirySupervisor.js +88 -0
- package/dist/worldInstanceLifecycle.js +103 -0
- package/dist/worldInstanceState.js +52 -0
- package/dist/worldInstances.js +478 -0
- package/dist/worldJoin.js +56 -0
- package/dist/worldLayers.js +151 -0
- package/dist/worldLeases.js +78 -0
- package/dist/worldManifest.js +25 -0
- package/dist/worldMovement.js +63 -0
- package/dist/worldPersistence.js +134 -0
- package/dist/worldProjection.js +221 -0
- package/dist/worldReact.js +110 -0
- package/dist/worldRecoveryActor.js +35 -0
- package/dist/worldReturnAnchor.js +49 -0
- package/dist/worldRoomHooks.js +57 -0
- package/dist/worldRoomPool.js +27 -0
- package/dist/worldRoomSteps.js +133 -0
- package/dist/worldSeatBinding.js +36 -0
- package/dist/worldServer.d.ts +6936 -0
- package/dist/worldServer.js +48 -0
- package/dist/worldSourceSeatPending.js +9 -0
- package/dist/worldStrategyFixtures.js +164 -0
- package/dist/worldTesting.js +27 -0
- package/dist/worldTransitionDefaults.js +198 -0
- package/dist/worldTransitionExecutor.js +519 -0
- package/dist/worldTransitionGroup.js +113 -0
- package/dist/worldTransitionPhysicalSteps.js +40 -0
- package/dist/worldTransitionResolver.js +228 -0
- package/dist/worldTransitionSeatGroup.js +64 -0
- package/dist/worldTransitionSeats.js +260 -0
- package/dist/worldTransitionState.js +95 -0
- package/dist/worldTransitions.js +101 -0
- package/package.json +189 -4
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,1123 @@
|
|
|
1
|
+
import { BudgetExceeded as e, ProtocolError as t, RoomAuthoringError as n, RoomForbidden as r, RoomGone as i, RoomHibernatePending as a } from "./errors.js";
|
|
2
|
+
import { simulationOwnData as o } from "./simulationAuthoring.js";
|
|
3
|
+
import { applyRoomPoolRuntimeDefaults as s } from "./roomPoolRuntimeDefaults.js";
|
|
4
|
+
import { captureRoomListing as c } from "./room.js";
|
|
5
|
+
import { RoomInputCodec as l, RoomStateCodec as u } from "./stateCodec.js";
|
|
6
|
+
import { GeometryManifestFragmentSchema as d } from "./geometryManifestChannel.js";
|
|
7
|
+
import { GeometryDeltaFragmentSchema as f } from "./geometryChannel.js";
|
|
8
|
+
import { GeometryEditMessageSchema as p } from "./geometryEditChannel.js";
|
|
9
|
+
import { canonicalRoomJson as m } from "./checkpointJson.js";
|
|
10
|
+
import "./ports.js";
|
|
11
|
+
import { captureLockstepJournalScope as h } from "./lockstepJournalCodec.js";
|
|
12
|
+
import { captureRoomSessionAdmissionEvidence as g } from "./sessionAdmission.js";
|
|
13
|
+
import { RoomServerSession as _ } from "./serverSession.js";
|
|
14
|
+
import { RoomHostLoopObservation as v } from "./hostLoopObservation.js";
|
|
15
|
+
import { GeometryChunkRequestSchema as y, GeometryChunkSnapshotFragmentSchema as b } from "./geometrySnapshotChannel.js";
|
|
16
|
+
import { RoomActor as x } from "./actor.js";
|
|
17
|
+
import { RoomHost as S } from "./host.js";
|
|
18
|
+
import { captureRoomSnapshotBudget as C, defaultRoomSnapshotBudget as w } from "./snapshotBudget.js";
|
|
19
|
+
import { RoomSpectatorProducer as T } from "./spectatorProducer.js";
|
|
20
|
+
import { activateRoomGeometryChange as E, activateRoomGeometryVersion as D, bindRoomGeometryEditorPoints as O, captureRoomGeometryResource as k, currentRoomGeometryMutations as A, currentRoomGeometryStreams as j, fenceRoomGeometryMutations as M, fenceRoomGeometryStreams as N, openRoomGeometryMutations as P, openRoomGeometryStreams as F, pumpRoomGeometryMutations as I, pumpRoomGeometryStreams as L } from "./geometryHost.js";
|
|
21
|
+
import { isRoomLockstepOwnedRoom as R } from "./lockstepOwnedRoom.js";
|
|
22
|
+
import { Effect as z, Result as B, Schema as V } from "effect";
|
|
23
|
+
import { createHash as H } from "node:crypto";
|
|
24
|
+
//#region src/runtime.ts
|
|
25
|
+
var U = (e) => H("sha256").update(e.bytes).update(m({
|
|
26
|
+
schemaHash: e.schemaHash,
|
|
27
|
+
schedules: e.schedules,
|
|
28
|
+
...e.worldReceipts === void 0 ? {} : { worldReceipts: e.worldReceipts },
|
|
29
|
+
inputReceipts: e.inputReceipts,
|
|
30
|
+
commandCursor: e.commandCursor
|
|
31
|
+
})).digest("hex"), W = (e) => {
|
|
32
|
+
let { bytes: t, ...n } = e;
|
|
33
|
+
return t.byteLength + Buffer.byteLength(m(n));
|
|
34
|
+
}, G = class {
|
|
35
|
+
capacity;
|
|
36
|
+
clock;
|
|
37
|
+
checkpoints;
|
|
38
|
+
host;
|
|
39
|
+
loopObservation = new v();
|
|
40
|
+
rooms = /* @__PURE__ */ new Map();
|
|
41
|
+
pending = /* @__PURE__ */ new Map();
|
|
42
|
+
heldPublication = /* @__PURE__ */ new Set();
|
|
43
|
+
terminal = /* @__PURE__ */ new Map();
|
|
44
|
+
withdrawn = /* @__PURE__ */ new Map();
|
|
45
|
+
drains = /* @__PURE__ */ new Map();
|
|
46
|
+
migrationNotified = /* @__PURE__ */ new WeakSet();
|
|
47
|
+
turning = !1;
|
|
48
|
+
closed = !1;
|
|
49
|
+
checkpointCommits = 0;
|
|
50
|
+
checkpointStateBytes = 0;
|
|
51
|
+
unchangedSnapshotsSkipped = 0;
|
|
52
|
+
poolDefaults;
|
|
53
|
+
snapshotBudget;
|
|
54
|
+
lastPeriodicRoom = null;
|
|
55
|
+
constructor(e, n, r, i = {}) {
|
|
56
|
+
if (this.capacity = e, this.clock = n, this.checkpoints = r, !i || typeof i != "object" || Array.isArray(i) || Object.keys(i).some((e) => ![
|
|
57
|
+
"snapshotBudget",
|
|
58
|
+
"snapshotBudgetFactory",
|
|
59
|
+
"poolDefaults"
|
|
60
|
+
].includes(e))) throw new t({ detail: "Invalid implemented Room runtime snapshot options" });
|
|
61
|
+
let a = i.poolDefaults === void 0 ? void 0 : o(i.poolDefaults, [
|
|
62
|
+
"maxCatchUpTicks",
|
|
63
|
+
"snapshotEveryMs",
|
|
64
|
+
"hibernate"
|
|
65
|
+
], [
|
|
66
|
+
"maxCatchUpTicks",
|
|
67
|
+
"snapshotEveryMs",
|
|
68
|
+
"hibernate"
|
|
69
|
+
]);
|
|
70
|
+
if (a && (!Number.isSafeInteger(a.maxCatchUpTicks) || a.maxCatchUpTicks < 1 || a.maxCatchUpTicks > 128 || !Number.isSafeInteger(a.snapshotEveryMs) || a.snapshotEveryMs < 1 || a.snapshotEveryMs > 2147483647 || typeof a.hibernate != "boolean")) throw new t({ detail: "Invalid pool runtime defaults" });
|
|
71
|
+
this.poolDefaults = a === void 0 ? void 0 : Object.freeze({ ...a }), this.snapshotBudget = C(i.snapshotBudgetFactory ?? w, i.snapshotBudget ?? {}), this.host = new S(e);
|
|
72
|
+
}
|
|
73
|
+
create(e, t, r, i, a, o, s) {
|
|
74
|
+
if (this.assertAdmission(e), !r.initialState) throw new n({
|
|
75
|
+
room: r.name,
|
|
76
|
+
detail: "Room creation requires author-owned initialState"
|
|
77
|
+
});
|
|
78
|
+
let c = V.decodeUnknownSync(r.options)(i), l = r.initialState(structuredClone(c));
|
|
79
|
+
return this.add(e, t, r, l, c, {
|
|
80
|
+
epoch: a,
|
|
81
|
+
commandCursor: 0,
|
|
82
|
+
revision: 0
|
|
83
|
+
}, o, s);
|
|
84
|
+
}
|
|
85
|
+
add(e, r, i, a, o, m, h, g) {
|
|
86
|
+
if (this.assertAdmission(e), m.worldRecoveryEpoch !== void 0 && (!m.publicationHeld || !i.world || !Number.isSafeInteger(m.worldRecoveryEpoch) || m.worldRecoveryEpoch < 1 || m.worldRecoveryEpoch > m.epoch)) throw new t({ detail: "World recovery baseline requires a held World actor and a retained prior epoch" });
|
|
87
|
+
if (!Number.isSafeInteger(m.revision) || m.revision < 0 || m.epoch < 1) throw new n({
|
|
88
|
+
room: e,
|
|
89
|
+
detail: "Runtime requires a durable positive ownership epoch and checkpoint revision"
|
|
90
|
+
});
|
|
91
|
+
i = s(i, this.poolDefaults);
|
|
92
|
+
let v = new u(i.state);
|
|
93
|
+
if (g.spectatorGroup && g.spectatorHistory) throw new t({ detail: "Choose one owned spectator group or explicit borrowed history" });
|
|
94
|
+
if (i.spectator && !g.spectatorGroup && !g.spectatorHistory) throw new t({ detail: "Configured spectator history requires an actual host view group" });
|
|
95
|
+
if (g.spectatorGroup && !i.spectator) throw new t({ detail: "Spectator group requires an explicit descriptor policy" });
|
|
96
|
+
if (g.replayRecording && (!g.spectatorGroup || !i.spectator)) throw new t({ detail: "Host replay recording requires its owned spectator producer and descriptor policy" });
|
|
97
|
+
if (i.spectator && g.spectatorHistory && Object.entries(i.spectator).some(([e, t]) => g.spectatorHistory?.history.limits[e] !== t)) throw new t({ detail: "Borrowed spectator history does not preserve the descriptor policy" });
|
|
98
|
+
let S = i.spectator && g.spectatorGroup ? new T(i.state, {
|
|
99
|
+
roomId: e,
|
|
100
|
+
tenantId: r,
|
|
101
|
+
name: i.name,
|
|
102
|
+
epoch: m.epoch
|
|
103
|
+
}, g.spectatorGroup, i.spectator, g.replayRecording) : void 0, C = {
|
|
104
|
+
...g,
|
|
105
|
+
spectatorHistory: S?.history ?? g.spectatorHistory
|
|
106
|
+
};
|
|
107
|
+
delete C.geometry;
|
|
108
|
+
let w = g.geometry ? k(g.geometry, {
|
|
109
|
+
roomId: e,
|
|
110
|
+
tenantId: r,
|
|
111
|
+
hostId: g.geometry.scope.hostId,
|
|
112
|
+
epoch: m.epoch,
|
|
113
|
+
name: i.name
|
|
114
|
+
}) : void 0, R = /* @__PURE__ */ new Set(), V = w ? P(w, () => [...R]) : void 0, H = w ? F(w, () => [...R]) : void 0, U = (e, n) => {
|
|
115
|
+
if (e?.channel !== V?.channel || e?.publicationChannel !== V?.publicationChannel || n?.channel !== H?.channel || n?.recovery?.requestChannel !== H?.recovery?.requestChannel || n?.recovery?.responseChannel !== H?.recovery?.responseChannel) throw new t({ detail: "Reloaded geometry graph must preserve its compiled Room channel identities" });
|
|
116
|
+
if (e) {
|
|
117
|
+
let n = i.messages[e.channel], r = i.messages[e.publicationChannel];
|
|
118
|
+
if (!n || !r || !n.reliable || !r.reliable || n.direction !== "client" || r.direction !== "server" || new l(n.schema).schemaHash !== new l(p).schemaHash || new l(r.schema).schemaHash !== new l(f).schemaHash) throw new t({ detail: "Host geometry mutations require both actual reliable compiled intention and delta channels" });
|
|
119
|
+
}
|
|
120
|
+
if (n) {
|
|
121
|
+
let e = i.messages[n.channel];
|
|
122
|
+
if (!e || !e.reliable || e.direction !== "server" || new l(e.schema).schemaHash !== new l(d).schemaHash) throw new t({ detail: "Host geometry streams require the actual reliable compiled metadata channel" });
|
|
123
|
+
}
|
|
124
|
+
if (n?.recovery) {
|
|
125
|
+
let r = i.messages[n.recovery.requestChannel], a = i.messages[n.recovery.responseChannel], o = [
|
|
126
|
+
n.channel,
|
|
127
|
+
n.recovery.requestChannel,
|
|
128
|
+
n.recovery.responseChannel,
|
|
129
|
+
...e ? [e.channel, e.publicationChannel] : []
|
|
130
|
+
];
|
|
131
|
+
if (new Set(o).size !== o.length || !r || !a || !r.reliable || !a.reliable || r.direction !== "client" || a.direction !== "server" || new l(r.schema).schemaHash !== new l(y).schemaHash || new l(a.schema).schemaHash !== new l(b).schemaHash) throw new t({ detail: "Host geometry recovery needs distinct actual compiled readonly request/reply channels" });
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
U(V, H);
|
|
135
|
+
let W = new x(e, i, a, o, this.clock, r, m, w?.view);
|
|
136
|
+
w && O(w, (e) => W.worldEntityPoint(e));
|
|
137
|
+
let G = null, K = !1, q = {
|
|
138
|
+
mode: "state-sync",
|
|
139
|
+
id: e,
|
|
140
|
+
tenantId: r,
|
|
141
|
+
epoch: m.epoch,
|
|
142
|
+
revision: m.revision,
|
|
143
|
+
sendInterval: 1e3 / i.sendRate,
|
|
144
|
+
maxSessions: i.maxClients,
|
|
145
|
+
nextSendAt: this.clock.now(),
|
|
146
|
+
sessions: R,
|
|
147
|
+
hibernateOnEmpty: i.autoDispose.hibernate,
|
|
148
|
+
snapshotEveryMs: i.snapshot.everyMs,
|
|
149
|
+
onlyIfChanged: i.snapshot.onlyIfChanged,
|
|
150
|
+
snapshotEncoding: Object.freeze({
|
|
151
|
+
mode: i.snapshot.mode,
|
|
152
|
+
fullEvery: i.snapshot.fullEvery,
|
|
153
|
+
keepFulls: i.snapshot.keepFulls,
|
|
154
|
+
store: i.snapshot.store,
|
|
155
|
+
maxInlineBytes: i.snapshot.maxInlineBytes
|
|
156
|
+
}),
|
|
157
|
+
nextSnapshotAt: this.clock.now(),
|
|
158
|
+
lastCheckpointFingerprint: null,
|
|
159
|
+
lastListing: null,
|
|
160
|
+
confirmInputCheckpoint: (e) => W.confirmInputCheckpoint(e),
|
|
161
|
+
activateWorldMembers: (e, t) => W.activateWorldReservedAsync(e, t),
|
|
162
|
+
cancelWorldGhost: (e, t, n) => W.cancelWorldGhost(e, t, n),
|
|
163
|
+
cancelWorldPreview: (e, t) => W.cancelWorldPreview(e, t),
|
|
164
|
+
previewWorldEnter: (e, t, n) => W.previewWorldEnter(e, t, n),
|
|
165
|
+
retireWorldReceipt: (e, t) => W.retireWorldReceipt(e, t),
|
|
166
|
+
holdPublication: () => W.holdPublication(),
|
|
167
|
+
releasePublication: () => W.releasePublication(),
|
|
168
|
+
worldRecoveryEpoch: m.worldRecoveryEpoch,
|
|
169
|
+
worldReceiptSnapshot: () => W.worldReceiptSnapshot(),
|
|
170
|
+
hasWorldReceipt: (e, t) => W.hasWorldReceipt(e, t),
|
|
171
|
+
applyWorldHook: (e, t, n, r, i, a, o, s, c) => W.applyWorldHook(e, t, n, r, i, a, o, s, c),
|
|
172
|
+
finalizeWorldExit: (e, t, n, r, i, a) => W.finalizeWorldExit(e, t, n, r, i, a),
|
|
173
|
+
isWorldFinalizationHeld: () => W.isWorldFinalizationHeld(),
|
|
174
|
+
notifyWorldHandoff: (e, n) => W.notifyWorldHandoff(e, n, (e) => {
|
|
175
|
+
let n = [...R].filter((e) => e.status === "joined");
|
|
176
|
+
if (n.some((e) => typeof e.notifyWorldHandoff != "function")) throw new t({ detail: "World notice requires the actual reliable Session capability" });
|
|
177
|
+
for (let t of n) t.notifyWorldHandoff(e);
|
|
178
|
+
}),
|
|
179
|
+
worldFinalizationAfterglow: () => W.worldFinalizationAfterglow(),
|
|
180
|
+
worldFinalizationRequest: () => W.worldFinalizationRequest(),
|
|
181
|
+
completeWorldFinalization: (e, t) => W.completeWorldFinalization(e, t),
|
|
182
|
+
reconcileWorldSource: (e, t, n, r) => W.reconcileWorldSource(e, t, n, r),
|
|
183
|
+
configureWorldCellMovement: (e, t, n) => W.configureWorldCellMovement(e, t, n),
|
|
184
|
+
captureWorldMovement: (e) => W.captureWorldMovement(e),
|
|
185
|
+
worldMovementSnapshot: () => W.worldMovementSnapshot(),
|
|
186
|
+
listWorldEntityIds: (e, t, n) => W.listWorldEntityIds(e, t, n),
|
|
187
|
+
captureWorldProjection: (e, t, n) => W.captureWorldProjection(e, t, n),
|
|
188
|
+
captureWorldEntity: (e, t, n) => W.captureWorldEntity(e, t, n),
|
|
189
|
+
hasCommands: () => W.metrics().outboxCommands > 0,
|
|
190
|
+
listing: () => i.listing === void 0 ? void 0 : c(i.name, i.listing({
|
|
191
|
+
state: W.lastGoodSnapshot().state,
|
|
192
|
+
options: o
|
|
193
|
+
})),
|
|
194
|
+
capture: () => {
|
|
195
|
+
let r = W.lastGoodSnapshot(), a = i.snapshot.pick(r.state);
|
|
196
|
+
if (z.isEffect(a) || a && typeof a == "object" && "then" in a) throw a instanceof Promise && a.catch(() => void 0), new n({
|
|
197
|
+
room: e,
|
|
198
|
+
detail: "Snapshot projection must return synchronous full-schema state"
|
|
199
|
+
});
|
|
200
|
+
let o = v.full(a);
|
|
201
|
+
if (B.isFailure(o)) throw o.failure;
|
|
202
|
+
let s = i.world ? W.worldReceiptSnapshot() : void 0;
|
|
203
|
+
if (s?.length) {
|
|
204
|
+
let e = v.full(r.state);
|
|
205
|
+
if (B.isFailure(e)) throw e.failure;
|
|
206
|
+
if (e.success.length !== o.success.length || e.success.some((e, t) => e !== o.success[t])) throw new t({ detail: "World hook receipts require the actual actor state in the same checkpoint" });
|
|
207
|
+
}
|
|
208
|
+
let c = q.listing();
|
|
209
|
+
return {
|
|
210
|
+
tick: r.tick,
|
|
211
|
+
bytes: o.success,
|
|
212
|
+
schemaHash: v.schemaHash,
|
|
213
|
+
schedules: W.scheduleSnapshot(),
|
|
214
|
+
...s === void 0 ? {} : { worldReceipts: s },
|
|
215
|
+
inputReceipts: W.inputReceiptSnapshot(),
|
|
216
|
+
commandCursor: W.commandCursor(),
|
|
217
|
+
commands: W.drainOutbox(),
|
|
218
|
+
...c === void 0 ? {} : { listing: c }
|
|
219
|
+
};
|
|
220
|
+
},
|
|
221
|
+
flush: () => W.flushClientOperations(),
|
|
222
|
+
dispose: () => G ??= W.disposeAsync(),
|
|
223
|
+
checkpointReady: () => !W.isLifecycleBusy(),
|
|
224
|
+
releaseHibernated: () => W.releaseHibernated(),
|
|
225
|
+
freezeForDrain: () => W.freezeForDrain(),
|
|
226
|
+
releaseTransferred: () => W.releaseTransferred(),
|
|
227
|
+
quiesceDrainGeometry: async () => {
|
|
228
|
+
w && (M(w), N(w), await w.quiesce());
|
|
229
|
+
},
|
|
230
|
+
produceSpectators: () => S?.capture(Math.floor(this.clock.now()), W.lastGoodSnapshot()),
|
|
231
|
+
clearSpectators: () => S?.clear(),
|
|
232
|
+
finishRecording: async () => {
|
|
233
|
+
S && g.replayRecording && !K && (S.capture(Math.floor(this.clock.now()), W.lastGoodSnapshot()), await S.finishRecording(), K = !0);
|
|
234
|
+
},
|
|
235
|
+
fenceGeometry: () => {
|
|
236
|
+
w && (M(w), N(w));
|
|
237
|
+
},
|
|
238
|
+
pumpGeometry: async () => {
|
|
239
|
+
w && (await I(w), await L(w));
|
|
240
|
+
},
|
|
241
|
+
synchronizeGeometry: async () => {
|
|
242
|
+
await w?.synchronize();
|
|
243
|
+
},
|
|
244
|
+
quiesceGeometry: async () => {
|
|
245
|
+
if (!w) throw new t({ detail: "Room has no actual geometry resource to quiesce" });
|
|
246
|
+
await w.quiesce();
|
|
247
|
+
},
|
|
248
|
+
activateGeometryVersion: async (e) => {
|
|
249
|
+
if (!w) throw new t({ detail: "Room has no actual geometry resource for version activation" });
|
|
250
|
+
await D(w, e, () => [...R], U);
|
|
251
|
+
},
|
|
252
|
+
activateGeometryChange: async (e) => {
|
|
253
|
+
if (!w) throw new t({ detail: "Room has no actual geometry resource for change activation" });
|
|
254
|
+
await E(w, e, () => [...R], U);
|
|
255
|
+
},
|
|
256
|
+
finishGeometry: async () => {
|
|
257
|
+
await w?.close();
|
|
258
|
+
},
|
|
259
|
+
connect: (e) => {
|
|
260
|
+
let n = new _(W, e, this.clock, h, {
|
|
261
|
+
...C,
|
|
262
|
+
epoch: m.epoch,
|
|
263
|
+
...V || H?.recovery ? { onClientMessage: (e, r, i) => {
|
|
264
|
+
let a = w ? j(w) : void 0, o = w ? A(w) : void 0;
|
|
265
|
+
if (H?.recovery && e === H.recovery.requestChannel) {
|
|
266
|
+
if (!a?.recovery) throw new t({ detail: "Room geometry recovery graph was retired" });
|
|
267
|
+
a.recovery.stage(n, r);
|
|
268
|
+
} else if (V && e === V.channel) {
|
|
269
|
+
if (!o) throw new t({ detail: "Room geometry mutation graph was retired" });
|
|
270
|
+
o.stage(n, r);
|
|
271
|
+
} else {
|
|
272
|
+
if (C.onClientMessage) return C.onClientMessage(e, r, i);
|
|
273
|
+
throw new t({ detail: "Actual Room client channel has no acquired Host handler" });
|
|
274
|
+
}
|
|
275
|
+
} } : {}
|
|
276
|
+
});
|
|
277
|
+
return n;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
return m.publicationHeld && W.holdPublication(), this.host.add(W), this.rooms.set(e, q), m.publicationHeld && this.heldPublication.add(e), W;
|
|
281
|
+
}
|
|
282
|
+
async activateWorldMembers(e, t, n, r, a) {
|
|
283
|
+
let o = this.rooms.get(e);
|
|
284
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.heldPublication.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.has(e)) throw new i({ roomId: e });
|
|
285
|
+
this.turning = !0;
|
|
286
|
+
try {
|
|
287
|
+
await o.activateWorldMembers(r, a);
|
|
288
|
+
} finally {
|
|
289
|
+
this.turning = !1;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
replaceWorldGhostProjection(e, t, n, r, i, a) {
|
|
293
|
+
return this.applyWorldHook(e, t, "ghost", n, i, void 0, a, !1, r, !0);
|
|
294
|
+
}
|
|
295
|
+
async cancelWorldGhost(e, t, n, r, a) {
|
|
296
|
+
let o = this.rooms.get(e);
|
|
297
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n.epoch || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
298
|
+
this.turning = !0;
|
|
299
|
+
try {
|
|
300
|
+
await o.cancelWorldGhost(n, r, a);
|
|
301
|
+
} finally {
|
|
302
|
+
this.turning = !1;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async cancelWorldPreview(e, t, n, r, a) {
|
|
306
|
+
let o = this.rooms.get(e);
|
|
307
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
308
|
+
this.turning = !0;
|
|
309
|
+
try {
|
|
310
|
+
await o.cancelWorldPreview(r, a);
|
|
311
|
+
} finally {
|
|
312
|
+
this.turning = !1;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
async previewWorldEnter(e, t, n, r, a) {
|
|
316
|
+
let o = this.rooms.get(e);
|
|
317
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n.epoch || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
318
|
+
this.turning = !0;
|
|
319
|
+
try {
|
|
320
|
+
await o.previewWorldEnter(n, r, a);
|
|
321
|
+
} finally {
|
|
322
|
+
this.turning = !1;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
async settleSessions(e, n, r) {
|
|
326
|
+
let a = this.rooms.get(e);
|
|
327
|
+
if (this.closed || this.turning || !a || a.tenantId !== n || a.epoch !== r || this.withdrawn.has(e) || this.drains.has(e)) throw new i({ roomId: e });
|
|
328
|
+
if ((await Promise.allSettled([...a.sessions].map((e) => e.settled()))).some((e) => e.status === "rejected")) throw new t({ detail: "Room Session authentication/lifecycle remains incomplete" });
|
|
329
|
+
}
|
|
330
|
+
worldLifecycleQuiet(e) {
|
|
331
|
+
let t = this.rooms.get(e);
|
|
332
|
+
return t !== void 0 && t.mode === "state-sync" && t.checkpointReady();
|
|
333
|
+
}
|
|
334
|
+
worldReceiptSnapshot(e, t, n) {
|
|
335
|
+
let r = this.rooms.get(e);
|
|
336
|
+
if (this.closed || this.turning || !r || r.mode !== "state-sync" || r.tenantId !== t || r.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e)) throw new i({ roomId: e });
|
|
337
|
+
return r.worldReceiptSnapshot();
|
|
338
|
+
}
|
|
339
|
+
async retireWorldReceipt(e, t, n, r, a) {
|
|
340
|
+
let o = this.rooms.get(e);
|
|
341
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
342
|
+
this.turning = !0;
|
|
343
|
+
try {
|
|
344
|
+
await o.retireWorldReceipt(r, a);
|
|
345
|
+
} finally {
|
|
346
|
+
this.turning = !1;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
hasWorldReceipt(e, t, n, r, a) {
|
|
350
|
+
let o = this.rooms.get(e);
|
|
351
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
352
|
+
return o.hasWorldReceipt(r, a);
|
|
353
|
+
}
|
|
354
|
+
async applyWorldHook(e, t, n, r, a, o, s, c, l, u, d) {
|
|
355
|
+
let f = this.rooms.get(e);
|
|
356
|
+
if (this.closed || this.turning || !f || f.mode !== "state-sync" || f.tenantId !== t || f.epoch !== r.epoch || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
357
|
+
this.turning = !0;
|
|
358
|
+
try {
|
|
359
|
+
await f.applyWorldHook(n, r, a, o, s, c, l, u, d);
|
|
360
|
+
} finally {
|
|
361
|
+
this.turning = !1;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
async finalizeWorldExit(e, t, n, r, a, o, s, c) {
|
|
365
|
+
let l = this.rooms.get(e);
|
|
366
|
+
if (this.closed || this.turning || !l || l.mode !== "state-sync" || l.tenantId !== t || l.epoch !== n.epoch || this.heldPublication.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
367
|
+
this.turning = !0;
|
|
368
|
+
try {
|
|
369
|
+
await l.finalizeWorldExit(n, r, a, o, s, c);
|
|
370
|
+
} finally {
|
|
371
|
+
this.turning = !1;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
worldFinalizationAfterglow(e, t, n) {
|
|
375
|
+
let r = this.rooms.get(e);
|
|
376
|
+
if (this.closed || !r || r.mode !== "state-sync" || r.tenantId !== t || r.epoch !== n) throw new i({ roomId: e });
|
|
377
|
+
return r.worldFinalizationAfterglow();
|
|
378
|
+
}
|
|
379
|
+
worldFinalizationRequest(e, t, n) {
|
|
380
|
+
let r = this.rooms.get(e);
|
|
381
|
+
if (this.closed || !r || r.mode !== "state-sync" || r.tenantId !== t || r.epoch !== n) throw new i({ roomId: e });
|
|
382
|
+
return r.worldFinalizationRequest();
|
|
383
|
+
}
|
|
384
|
+
async notifyWorldHandoff(e, t, n, r) {
|
|
385
|
+
let a = this.rooms.get(e);
|
|
386
|
+
if (this.closed || this.turning || !a || a.mode !== "state-sync" || a.tenantId !== t || a.epoch !== n.sourceEpoch || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.has(e)) throw new i({ roomId: e });
|
|
387
|
+
this.turning = !0;
|
|
388
|
+
try {
|
|
389
|
+
await a.notifyWorldHandoff(n, r);
|
|
390
|
+
} finally {
|
|
391
|
+
this.turning = !1;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
async completeWorldFinalization(e, t, n, r, a) {
|
|
395
|
+
let o = this.rooms.get(e);
|
|
396
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.has(e)) throw new i({ roomId: e });
|
|
397
|
+
this.turning = !0;
|
|
398
|
+
try {
|
|
399
|
+
await o.completeWorldFinalization(r, a);
|
|
400
|
+
} finally {
|
|
401
|
+
this.turning = !1;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
async reconcileWorldSource(e, t, n, r, a, o) {
|
|
405
|
+
let s = this.rooms.get(e);
|
|
406
|
+
if (this.closed || this.turning || !s || s.mode !== "state-sync" || s.tenantId !== t || s.epoch !== n.epoch || !this.heldPublication.has(e) && !s.isWorldFinalizationHeld() || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
407
|
+
this.turning = !0;
|
|
408
|
+
try {
|
|
409
|
+
await s.reconcileWorldSource(n, r, a, o);
|
|
410
|
+
} finally {
|
|
411
|
+
this.turning = !1;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
async configureWorldCellMovement(e, t, n, r, a) {
|
|
415
|
+
let o = this.rooms.get(e);
|
|
416
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
417
|
+
this.turning = !0;
|
|
418
|
+
try {
|
|
419
|
+
await o.configureWorldCellMovement(n, r, a);
|
|
420
|
+
} finally {
|
|
421
|
+
this.turning = !1;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
async captureWorldMovement(e, t, n) {
|
|
425
|
+
let r = this.rooms.get(e);
|
|
426
|
+
if (this.closed || this.turning || !r || r.mode !== "state-sync" || r.tenantId !== t || r.epoch !== n || this.heldPublication.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
427
|
+
this.turning = !0;
|
|
428
|
+
try {
|
|
429
|
+
return await r.captureWorldMovement(n);
|
|
430
|
+
} finally {
|
|
431
|
+
this.turning = !1;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
worldMovementSnapshot(e, t, n) {
|
|
435
|
+
let r = this.rooms.get(e);
|
|
436
|
+
if (this.closed || !r || r.mode !== "state-sync" || r.tenantId !== t || r.epoch !== n) throw new i({ roomId: e });
|
|
437
|
+
return r.worldMovementSnapshot();
|
|
438
|
+
}
|
|
439
|
+
async listWorldEntityIds(e, t, n, r, a) {
|
|
440
|
+
let o = this.rooms.get(e);
|
|
441
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.heldPublication.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
442
|
+
this.turning = !0;
|
|
443
|
+
try {
|
|
444
|
+
return await o.listWorldEntityIds(n, r, a);
|
|
445
|
+
} finally {
|
|
446
|
+
this.turning = !1;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async captureWorldProjection(e, t, n, r, a) {
|
|
450
|
+
let o = this.rooms.get(e);
|
|
451
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.heldPublication.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
452
|
+
this.turning = !0;
|
|
453
|
+
try {
|
|
454
|
+
return await o.captureWorldProjection(r, n, a);
|
|
455
|
+
} finally {
|
|
456
|
+
this.turning = !1;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
async captureWorldEntity(e, t, n, r, a) {
|
|
460
|
+
let o = this.rooms.get(e);
|
|
461
|
+
if (this.closed || this.turning || !o || o.mode !== "state-sync" || o.tenantId !== t || o.epoch !== n || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
462
|
+
this.turning = !0;
|
|
463
|
+
try {
|
|
464
|
+
return await o.captureWorldEntity(r, n, a);
|
|
465
|
+
} finally {
|
|
466
|
+
this.turning = !1;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
async synchronizeGeometry(e) {
|
|
470
|
+
if (this.drains.has(e)) throw new i({ roomId: e });
|
|
471
|
+
if (this.turning) throw new n({
|
|
472
|
+
room: e,
|
|
473
|
+
detail: "Geometry directory synchronization must stay outside the host turn"
|
|
474
|
+
});
|
|
475
|
+
let t = this.rooms.get(e);
|
|
476
|
+
t?.mode === "state-sync" && await t.synchronizeGeometry();
|
|
477
|
+
}
|
|
478
|
+
async quiesceGeometry(e) {
|
|
479
|
+
if (this.drains.has(e)) throw new i({ roomId: e });
|
|
480
|
+
let t = this.rooms.get(e);
|
|
481
|
+
if (this.closed || this.turning || !t || t.mode !== "state-sync" || this.terminal.has(e) || this.withdrawn.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
482
|
+
this.turning = !0;
|
|
483
|
+
try {
|
|
484
|
+
await t.quiesceGeometry();
|
|
485
|
+
} finally {
|
|
486
|
+
this.turning = !1;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
async activateGeometryVersion(e, t) {
|
|
490
|
+
if (this.drains.has(e)) throw new i({ roomId: e });
|
|
491
|
+
let n = this.rooms.get(e);
|
|
492
|
+
if (this.closed || this.turning || !n || n.mode !== "state-sync" || this.terminal.has(e) || this.withdrawn.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
493
|
+
this.turning = !0;
|
|
494
|
+
try {
|
|
495
|
+
await n.activateGeometryVersion(t);
|
|
496
|
+
} finally {
|
|
497
|
+
this.turning = !1;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
async activateGeometryChange(e, t) {
|
|
501
|
+
if (this.drains.has(e)) throw new i({ roomId: e });
|
|
502
|
+
let n = this.rooms.get(e);
|
|
503
|
+
if (this.closed || this.turning || !n || n.mode !== "state-sync" || this.terminal.has(e) || this.withdrawn.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
504
|
+
this.turning = !0;
|
|
505
|
+
try {
|
|
506
|
+
await n.activateGeometryChange(t);
|
|
507
|
+
} finally {
|
|
508
|
+
this.turning = !1;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
addLockstep(e, n) {
|
|
512
|
+
if (!R(e) || e.isDisposed()) throw new t({ detail: "Runtime requires the genuine live SQL-created Lockstep owner" });
|
|
513
|
+
this.assertAdmission(e.id);
|
|
514
|
+
let r = o(n, ["terminal", "runEffect"], ["terminal", "runEffect"]), i = o(r.terminal, ["terminate"], ["terminate"]);
|
|
515
|
+
if (typeof r.runEffect != "function" || typeof i.terminate != "function") throw new t({ detail: "Runtime Lockstep requires complete terminal capability and actual Effect runner" });
|
|
516
|
+
let a = Object.freeze({
|
|
517
|
+
runEffect: r.runEffect,
|
|
518
|
+
terminal: Object.freeze({ terminate: i.terminate.bind(r.terminal) })
|
|
519
|
+
}), s = {
|
|
520
|
+
mode: "lockstep",
|
|
521
|
+
id: e.id,
|
|
522
|
+
tenantId: e.tenantId,
|
|
523
|
+
epoch: e.epoch,
|
|
524
|
+
maxSessions: e.descriptor.maxClients,
|
|
525
|
+
sessions: /* @__PURE__ */ new Set(),
|
|
526
|
+
owner: e,
|
|
527
|
+
binding: a,
|
|
528
|
+
connect: (t) => e.connect(t)
|
|
529
|
+
};
|
|
530
|
+
this.host.add(e), this.rooms.set(e.id, s);
|
|
531
|
+
}
|
|
532
|
+
async publishLockstep(e) {
|
|
533
|
+
let t = this.rooms.get(e);
|
|
534
|
+
if (this.closed || this.turning || !t || t.mode !== "lockstep" || this.terminal.has(e) || this.withdrawn.has(e)) throw new i({ roomId: e });
|
|
535
|
+
this.turning = !0;
|
|
536
|
+
try {
|
|
537
|
+
await t.owner.publishAsync();
|
|
538
|
+
} finally {
|
|
539
|
+
this.turning = !1;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
lockstepRosterOpen(e) {
|
|
543
|
+
let t = this.rooms.get(e);
|
|
544
|
+
return !this.closed && !this.turning && t?.mode === "lockstep" && !this.terminal.has(e) && !this.withdrawn.has(e) && t.owner.rosterOpen();
|
|
545
|
+
}
|
|
546
|
+
admitLockstep(e, n, r) {
|
|
547
|
+
let i = this.rooms.get(e);
|
|
548
|
+
if (this.closed || this.turning || !i || i.mode !== "lockstep" || this.terminal.has(e) || this.withdrawn.has(e) || !i.sessions.has(r)) throw new t({ detail: "Runtime Lockstep admission requires its exact owned actual Session outside a turn" });
|
|
549
|
+
return i.owner.admit(n, r);
|
|
550
|
+
}
|
|
551
|
+
async prepareLockstepInitialRoster(e, t = {}) {
|
|
552
|
+
let n = this.rooms.get(e);
|
|
553
|
+
if (this.closed || this.turning || !n || n.mode !== "lockstep" || this.terminal.has(e) || this.withdrawn.has(e)) throw new i({ roomId: e });
|
|
554
|
+
this.turning = !0;
|
|
555
|
+
try {
|
|
556
|
+
return await n.owner.prepareInitialRoster(t);
|
|
557
|
+
} finally {
|
|
558
|
+
this.turning = !1;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
async startLockstep(e) {
|
|
562
|
+
let t = this.rooms.get(e);
|
|
563
|
+
if (this.closed || this.turning || !t || t.mode !== "lockstep" || this.terminal.has(e) || this.withdrawn.has(e)) throw new i({ roomId: e });
|
|
564
|
+
this.turning = !0;
|
|
565
|
+
try {
|
|
566
|
+
return await t.owner.startAsync();
|
|
567
|
+
} finally {
|
|
568
|
+
this.turning = !1;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
assertAdmission(t) {
|
|
572
|
+
if (this.closed) throw new i({ roomId: t });
|
|
573
|
+
if (this.turning) throw new n({
|
|
574
|
+
room: t,
|
|
575
|
+
detail: "Runtime admission must wait for the current host turn"
|
|
576
|
+
});
|
|
577
|
+
if (this.rooms.has(t)) throw new n({
|
|
578
|
+
room: t,
|
|
579
|
+
detail: "Room is already owned by this runtime"
|
|
580
|
+
});
|
|
581
|
+
if (this.rooms.size >= this.capacity) throw new e({
|
|
582
|
+
budget: "runtimeRooms",
|
|
583
|
+
limit: this.capacity
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
holdPublication(e) {
|
|
587
|
+
let n = this.rooms.get(e);
|
|
588
|
+
if (this.closed || this.turning || !n || n.mode !== "state-sync" || n.sessions.size || n.lastCheckpointFingerprint !== null || this.pending.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e)) throw new t({ detail: "Publication hold requires an unstarted owned state-sync actor" });
|
|
589
|
+
n.holdPublication(), this.heldPublication.add(e);
|
|
590
|
+
}
|
|
591
|
+
isPublicationHeld(e) {
|
|
592
|
+
return this.heldPublication.has(e);
|
|
593
|
+
}
|
|
594
|
+
async publishHeld(e, n) {
|
|
595
|
+
if (!this.heldPublication.has(e)) throw new t({ detail: "Publication requires its retained hold" });
|
|
596
|
+
await this.persistRoom(e, !0), n && await n();
|
|
597
|
+
let r = this.rooms.get(e);
|
|
598
|
+
if (!r || r.mode !== "state-sync") throw new i({ roomId: e });
|
|
599
|
+
r.releasePublication(), this.heldPublication.delete(e);
|
|
600
|
+
}
|
|
601
|
+
persist(e) {
|
|
602
|
+
return this.persistRoom(e, !1);
|
|
603
|
+
}
|
|
604
|
+
async persistRoom(e, r) {
|
|
605
|
+
if (this.closed || !this.rooms.has(e) || this.withdrawn.has(e) || this.drains.has(e)) throw new i({ roomId: e });
|
|
606
|
+
if (this.rooms.get(e)?.mode === "lockstep") throw new t({ detail: "Lockstep creation is persisted by SQL Admission, never a state checkpoint" });
|
|
607
|
+
if (this.turning) throw new n({
|
|
608
|
+
room: e,
|
|
609
|
+
detail: "Persistence must wait for the current host turn"
|
|
610
|
+
});
|
|
611
|
+
this.turning = !0;
|
|
612
|
+
try {
|
|
613
|
+
await this.commitPending();
|
|
614
|
+
let a = this.rooms.get(e);
|
|
615
|
+
if (!a) throw new i({ roomId: e });
|
|
616
|
+
if (a.mode === "lockstep") throw new t({ detail: "Lockstep creation is persisted by SQL Admission, never a state checkpoint" });
|
|
617
|
+
if (!a.checkpointReady()) throw new n({
|
|
618
|
+
room: e,
|
|
619
|
+
detail: "Initial checkpoint must wait for lifecycle work"
|
|
620
|
+
});
|
|
621
|
+
this.heldPublication.has(e) || a.produceSpectators(), this.capture(a, "live", void 0, !1, this.heldPublication.has(e) && !r), await this.commitPending();
|
|
622
|
+
} finally {
|
|
623
|
+
this.turning = !1;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
connect(t, n) {
|
|
627
|
+
let r = this.rooms.get(t);
|
|
628
|
+
if (this.closed || !r || this.heldPublication.has(t) || this.pending.get(t)?.retire || this.terminal.has(t) || this.withdrawn.has(t) || this.drains.has(t)) throw new i({ roomId: t });
|
|
629
|
+
if (r.sessions.size >= r.maxSessions) throw new e({
|
|
630
|
+
budget: "roomSessions",
|
|
631
|
+
limit: r.maxSessions
|
|
632
|
+
});
|
|
633
|
+
let a = r.connect(n);
|
|
634
|
+
return r.sessions.add(a), a;
|
|
635
|
+
}
|
|
636
|
+
readSessionAdmission(e, n) {
|
|
637
|
+
let r = this.rooms.get(e);
|
|
638
|
+
if (this.closed || !r || this.pending.get(e)?.retire || this.terminal.has(e) || this.withdrawn.has(e) || this.drains.has(e)) return null;
|
|
639
|
+
for (let i of r.sessions) {
|
|
640
|
+
if (i.id !== n || typeof i.admittedIdentity != "function") continue;
|
|
641
|
+
let r = i.admittedIdentity();
|
|
642
|
+
if (!r) return null;
|
|
643
|
+
let a = g(r);
|
|
644
|
+
if (a.roomId !== e || a.sessionId !== n) throw new t({ detail: "Actual Room session admission escaped its host scope" });
|
|
645
|
+
return a;
|
|
646
|
+
}
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
async leaveSession(e, t) {
|
|
650
|
+
let r = this.rooms.get(e);
|
|
651
|
+
if (r) {
|
|
652
|
+
if (r.mode === "lockstep" && this.turning) throw new n({
|
|
653
|
+
room: e,
|
|
654
|
+
detail: "Lockstep Session departure must await the current turn"
|
|
655
|
+
});
|
|
656
|
+
for (let e of r.sessions) e.id === t && (await e.close("left"), await e.settled(), r.mode === "lockstep" && await r.owner.maintenance(), r.sessions.delete(e));
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
async kickSubject(e, i, a, o) {
|
|
660
|
+
let s = this.rooms.get(e);
|
|
661
|
+
if (!s) return 0;
|
|
662
|
+
if (s.tenantId !== i) throw new r({ roomId: e });
|
|
663
|
+
if (s.mode === "lockstep" && this.turning) throw new n({
|
|
664
|
+
room: e,
|
|
665
|
+
detail: "Lockstep kick must await the current turn"
|
|
666
|
+
});
|
|
667
|
+
let c = 0;
|
|
668
|
+
for (let e of [...s.sessions]) {
|
|
669
|
+
let n = typeof e.admittedIdentity == "function" ? e.admittedIdentity() : null;
|
|
670
|
+
if (!(n === null || n.tenantId !== i || a !== null && n.subjectId !== a)) {
|
|
671
|
+
if (typeof e.kick != "function") throw new t({ detail: "Room session provider cannot kick" });
|
|
672
|
+
await e.kick(o), await e.settled(), s.mode === "lockstep" && await s.owner.maintenance(), s.sessions.delete(e), c++;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
return c;
|
|
676
|
+
}
|
|
677
|
+
async withdrawOwnership(e, r, i) {
|
|
678
|
+
if (this.turning) throw new n({
|
|
679
|
+
room: e,
|
|
680
|
+
detail: "Ownership withdrawal must wait for the current host turn"
|
|
681
|
+
});
|
|
682
|
+
let a = this.rooms.get(e);
|
|
683
|
+
if (a) {
|
|
684
|
+
if (a.tenantId !== r || a.epoch !== i) throw new t({ detail: "Revoked ownership tuple does not match the retained actor" });
|
|
685
|
+
this.turning = !0;
|
|
686
|
+
try {
|
|
687
|
+
this.withdrawn.has(e) || (this.host.take(e), this.withdrawn.set(e, {
|
|
688
|
+
disposed: !1,
|
|
689
|
+
disposalFailure: null
|
|
690
|
+
})), await this.finishWithdrawal(e);
|
|
691
|
+
} finally {
|
|
692
|
+
this.turning = !1;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
async prepareDrain(e) {
|
|
697
|
+
if (this.closed || this.turning) throw new t({ detail: "Drain preparation requires the exclusive live runtime lane" });
|
|
698
|
+
let n = this.rooms.get(e);
|
|
699
|
+
if (!n || this.heldPublication.has(e) || this.terminal.has(e) || this.withdrawn.has(e) || this.pending.get(e)?.retire) throw new i({ roomId: e });
|
|
700
|
+
let r = [...n.sessions];
|
|
701
|
+
if (r.some((e) => typeof e.quiesceForDrain != "function" || typeof e.notifyMigration != "function")) throw new t({ detail: "Planned drain requires actual Session quiescence and migration capabilities" });
|
|
702
|
+
this.turning = !0;
|
|
703
|
+
let a = this.drains.get(e);
|
|
704
|
+
a || (a = {
|
|
705
|
+
frozen: !1,
|
|
706
|
+
checkpoint: null,
|
|
707
|
+
ready: !1
|
|
708
|
+
}, this.drains.set(e, a), this.host.take(e));
|
|
709
|
+
try {
|
|
710
|
+
if (n.mode === "lockstep") {
|
|
711
|
+
let e = await n.owner.prepareDrain();
|
|
712
|
+
return a.frozen = !0, a.ready = !0, e;
|
|
713
|
+
}
|
|
714
|
+
if (!a.frozen) {
|
|
715
|
+
await this.commitPending(e);
|
|
716
|
+
let i = (await Promise.allSettled(r.map(async (e) => {
|
|
717
|
+
let n = e.quiesceForDrain();
|
|
718
|
+
if (!(n instanceof Promise)) throw new t({ detail: "Session quiescence must return its actual lifetime" });
|
|
719
|
+
await n;
|
|
720
|
+
}))).flatMap((e) => e.status === "rejected" ? [e.reason] : []);
|
|
721
|
+
if (i.length) throw AggregateError(i, "Session drain preparation remains incomplete");
|
|
722
|
+
if (n.flush(), await Promise.all(r.map((e) => e.settled())), r.some((e) => e.failure !== null)) throw new t({ detail: "Session work failed before the final drain snapshot" });
|
|
723
|
+
await n.quiesceDrainGeometry(), await n.freezeForDrain(), a.frozen = !0;
|
|
724
|
+
}
|
|
725
|
+
if (!a.checkpoint) try {
|
|
726
|
+
a.checkpoint = this.capture(n, "live");
|
|
727
|
+
} catch (t) {
|
|
728
|
+
throw a.checkpoint = this.pending.get(e)?.checkpoint ?? null, t;
|
|
729
|
+
}
|
|
730
|
+
return await this.commitPending(e), a.ready = !0, Object.freeze({
|
|
731
|
+
mode: "state-sync",
|
|
732
|
+
roomId: e,
|
|
733
|
+
tenantId: n.tenantId,
|
|
734
|
+
epoch: n.epoch,
|
|
735
|
+
revision: a.checkpoint.revision,
|
|
736
|
+
tick: a.checkpoint.tick
|
|
737
|
+
});
|
|
738
|
+
} finally {
|
|
739
|
+
this.turning = !1;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
async notifyDrainMigration(e, n) {
|
|
743
|
+
let r = this.rooms.get(e);
|
|
744
|
+
if (this.closed || this.turning || !r || !this.drains.get(e)?.ready) throw new t({ detail: "Migration notification requires the retained prepared Room boundary" });
|
|
745
|
+
this.turning = !0;
|
|
746
|
+
try {
|
|
747
|
+
let e = (await Promise.allSettled([...r.sessions].map(async (e) => {
|
|
748
|
+
if (this.migrationNotified.has(e)) return;
|
|
749
|
+
if (!e.notifyMigration) throw new t({ detail: "Owned Session lacks its migration writer" });
|
|
750
|
+
let r = e.notifyMigration(n);
|
|
751
|
+
if (!(r instanceof Promise)) throw new t({ detail: "Migration writer must return its actual native lifetime" });
|
|
752
|
+
await r, this.migrationNotified.add(e);
|
|
753
|
+
}))).flatMap((e) => e.status === "rejected" ? [e.reason] : []);
|
|
754
|
+
if (e.length) throw AggregateError(e, "Migration notification retains failed native writes");
|
|
755
|
+
} finally {
|
|
756
|
+
this.turning = !1;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
async finishWithdrawal(e) {
|
|
760
|
+
let t = this.rooms.get(e), r = this.withdrawn.get(e);
|
|
761
|
+
if (!t || !r) throw new n({
|
|
762
|
+
room: e,
|
|
763
|
+
detail: "Revoked actor cleanup has lost its retained owner"
|
|
764
|
+
});
|
|
765
|
+
if (t.mode === "lockstep") {
|
|
766
|
+
await t.owner.disposeAsync(!0), t.sessions.clear(), this.pending.delete(e), this.terminal.delete(e), this.rooms.delete(e), this.heldPublication.delete(e), this.withdrawn.delete(e), this.snapshotBudget.forget(e), this.drains.delete(e);
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
let i = [];
|
|
770
|
+
this.drains.get(e)?.frozen && !r.disposed && (t.releaseTransferred(), r.disposed = !0);
|
|
771
|
+
for (let e of t.sessions) try {
|
|
772
|
+
await e.closeFenced(), t.sessions.delete(e);
|
|
773
|
+
} catch (e) {
|
|
774
|
+
i.push(e);
|
|
775
|
+
}
|
|
776
|
+
if (!i.length && !r.disposed) try {
|
|
777
|
+
this.pending.get(e)?.checkpoint.disposition === "hibernated" ? t.releaseHibernated() : await t.dispose(), r.disposed = !0;
|
|
778
|
+
} catch (e) {
|
|
779
|
+
r.disposalFailure = e, r.disposed = !0;
|
|
780
|
+
}
|
|
781
|
+
if (t.mode === "state-sync") try {
|
|
782
|
+
await t.finishGeometry();
|
|
783
|
+
} catch (e) {
|
|
784
|
+
i.push(e);
|
|
785
|
+
}
|
|
786
|
+
if (r.disposalFailure !== null && i.push(r.disposalFailure), i.length) throw AggregateError(i, "Revoked Room owner cleanup failed; resources remain retained");
|
|
787
|
+
t.clearSpectators(), this.pending.delete(e), this.terminal.delete(e), this.rooms.delete(e), this.heldPublication.delete(e), this.withdrawn.delete(e), this.snapshotBudget.forget(e), this.drains.delete(e);
|
|
788
|
+
}
|
|
789
|
+
restore(e, n, r, a, o, s, c = !1) {
|
|
790
|
+
if (e.disposition === "disposed") throw new i({ roomId: e.roomId });
|
|
791
|
+
if (!Number.isSafeInteger(a) || a <= e.epoch) throw new t({ detail: "Rehydration requires a newer durable ownership epoch" });
|
|
792
|
+
let l = new u(n.state);
|
|
793
|
+
if (l.schemaHash !== e.schemaHash) throw new t({ detail: "Rehydration schema does not match the durable snapshot" });
|
|
794
|
+
let d = l.decodeFull(e.bytes);
|
|
795
|
+
if (B.isFailure(d)) throw d.failure;
|
|
796
|
+
return this.add(e.roomId, e.tenantId, n, d.success, r, {
|
|
797
|
+
epoch: a,
|
|
798
|
+
tick: e.tick,
|
|
799
|
+
commandCursor: e.commandCursor,
|
|
800
|
+
revision: e.revision,
|
|
801
|
+
schedules: e.schedules,
|
|
802
|
+
worldReceipts: e.worldReceipts,
|
|
803
|
+
rehydrate: !0,
|
|
804
|
+
publicationHeld: c,
|
|
805
|
+
...c && n.world ? { worldRecoveryEpoch: e.worldRecoveryEpoch ?? e.epoch } : {}
|
|
806
|
+
}, o, s);
|
|
807
|
+
}
|
|
808
|
+
capture(e, t, r, i = !1, a = !1) {
|
|
809
|
+
if (this.pending.has(e.id)) throw new n({
|
|
810
|
+
room: e.id,
|
|
811
|
+
detail: "An uncommitted checkpoint cannot be overwritten"
|
|
812
|
+
});
|
|
813
|
+
if (e.revision >= 2 ** 53 - 1) throw new n({
|
|
814
|
+
room: e.id,
|
|
815
|
+
detail: "Checkpoint revision is exhausted"
|
|
816
|
+
});
|
|
817
|
+
let o = r ?? e.capture(), s = e.revision + 1, c = Object.freeze({
|
|
818
|
+
...o,
|
|
819
|
+
roomId: e.id,
|
|
820
|
+
tenantId: e.tenantId,
|
|
821
|
+
epoch: e.epoch,
|
|
822
|
+
revision: s,
|
|
823
|
+
requestId: `${e.id}:${e.epoch}:checkpoint:${s}`,
|
|
824
|
+
disposition: t,
|
|
825
|
+
...a ? {
|
|
826
|
+
publication: "held",
|
|
827
|
+
...e.worldRecoveryEpoch === void 0 ? {} : { worldRecoveryEpoch: e.worldRecoveryEpoch }
|
|
828
|
+
} : {},
|
|
829
|
+
snapshot: e.snapshotEncoding
|
|
830
|
+
});
|
|
831
|
+
return i && !this.snapshotBudget.periodic(e.id, W(c), this.clock.now()) ? null : (e.revision = s, this.pending.set(e.id, {
|
|
832
|
+
checkpoint: c,
|
|
833
|
+
room: e,
|
|
834
|
+
retire: t === "disposed" || t === "faulted" || t === "hibernated"
|
|
835
|
+
}), i || (this.snapshotBudget.forget(e.id), this.snapshotBudget.forced(W(c), this.clock.now())), c);
|
|
836
|
+
}
|
|
837
|
+
async commitPending(e) {
|
|
838
|
+
let t = [];
|
|
839
|
+
for (let [n, r] of this.pending) if ((e === void 0 || n === e) && !this.withdrawn.has(n)) try {
|
|
840
|
+
let e = await z.runPromise(z.result(this.checkpoints.commit(structuredClone(r.checkpoint))));
|
|
841
|
+
if (B.isFailure(e)) {
|
|
842
|
+
if (e.failure instanceof a && r.checkpoint.disposition === "hibernated" && e.failure.roomId === n) continue;
|
|
843
|
+
throw e.failure;
|
|
844
|
+
}
|
|
845
|
+
r.room.confirmInputCheckpoint(r.checkpoint.inputReceipts), await r.room.synchronizeGeometry(), r.checkpoint.disposition === "hibernated" && (r.room.releaseHibernated(), await r.room.finishGeometry()), r.room.lastCheckpointFingerprint = U(r.checkpoint), r.checkpoint.listing !== void 0 && (r.room.lastListing = m(r.checkpoint.listing)), r.room.nextSnapshotAt = this.clock.now() + r.room.snapshotEveryMs, this.checkpointCommits++, this.checkpointStateBytes += r.checkpoint.bytes.byteLength, this.pending.delete(n), r.retire && (this.rooms.delete(n), this.heldPublication.delete(n), this.terminal.delete(n), this.snapshotBudget.forget(n));
|
|
846
|
+
} catch (e) {
|
|
847
|
+
t.push(e);
|
|
848
|
+
}
|
|
849
|
+
if (t.length) throw AggregateError(t, "Room checkpoint commit failed; retained for retry");
|
|
850
|
+
}
|
|
851
|
+
async retire(e, t = !1) {
|
|
852
|
+
e.fenceGeometry();
|
|
853
|
+
try {
|
|
854
|
+
await e.pumpGeometry();
|
|
855
|
+
} catch (e) {
|
|
856
|
+
return [e];
|
|
857
|
+
}
|
|
858
|
+
let n = [];
|
|
859
|
+
for (let t of e.sessions) try {
|
|
860
|
+
await t.close("disposed"), await t.settled(), e.sessions.delete(t);
|
|
861
|
+
} catch (e) {
|
|
862
|
+
try {
|
|
863
|
+
await t.settled();
|
|
864
|
+
} catch (e) {
|
|
865
|
+
n.push(e);
|
|
866
|
+
}
|
|
867
|
+
n.push(e);
|
|
868
|
+
}
|
|
869
|
+
if (n.length) return n;
|
|
870
|
+
try {
|
|
871
|
+
await e.finishRecording();
|
|
872
|
+
} catch (e) {
|
|
873
|
+
return [e];
|
|
874
|
+
}
|
|
875
|
+
if (!t) try {
|
|
876
|
+
await e.dispose();
|
|
877
|
+
} catch (e) {
|
|
878
|
+
n.push(e);
|
|
879
|
+
}
|
|
880
|
+
if (!t) try {
|
|
881
|
+
await e.finishGeometry();
|
|
882
|
+
} catch (e) {
|
|
883
|
+
n.push(e);
|
|
884
|
+
}
|
|
885
|
+
try {
|
|
886
|
+
e.flush();
|
|
887
|
+
} catch (e) {
|
|
888
|
+
n.push(e);
|
|
889
|
+
}
|
|
890
|
+
return n.length || e.clearSpectators(), n;
|
|
891
|
+
}
|
|
892
|
+
async captureTerminal(e) {
|
|
893
|
+
let r = [];
|
|
894
|
+
for (let [i, a] of this.terminal) {
|
|
895
|
+
if (e !== void 0 && i !== e) continue;
|
|
896
|
+
let s = this.rooms.get(i);
|
|
897
|
+
if (!s) throw new n({
|
|
898
|
+
room: i,
|
|
899
|
+
detail: "Host transferred an unowned room"
|
|
900
|
+
});
|
|
901
|
+
if (s.mode === "lockstep") try {
|
|
902
|
+
if (await s.owner.disposeAsync(), s.sessions.clear(), a.cleaned = !0, a.disposition === "hibernating") throw new t({ detail: "Lockstep has no state-checkpoint hibernation path" });
|
|
903
|
+
let e = h({
|
|
904
|
+
roomId: i,
|
|
905
|
+
tenantId: s.tenantId,
|
|
906
|
+
epoch: s.epoch
|
|
907
|
+
}), n = Object.freeze({
|
|
908
|
+
...e,
|
|
909
|
+
disposition: a.disposition
|
|
910
|
+
}), r = s.binding.terminal.terminate(n);
|
|
911
|
+
if (!z.isEffect(r)) throw new t({ detail: "Lockstep terminal capability must return its actual Effect" });
|
|
912
|
+
let c = o(await s.binding.runEffect(r), [
|
|
913
|
+
"roomId",
|
|
914
|
+
"tenantId",
|
|
915
|
+
"epoch",
|
|
916
|
+
"disposition",
|
|
917
|
+
"hostId"
|
|
918
|
+
], [
|
|
919
|
+
"roomId",
|
|
920
|
+
"tenantId",
|
|
921
|
+
"epoch",
|
|
922
|
+
"disposition",
|
|
923
|
+
"hostId"
|
|
924
|
+
]);
|
|
925
|
+
if (c.roomId !== i || c.tenantId !== s.tenantId || c.epoch !== s.epoch || c.disposition !== a.disposition || c.hostId !== s.owner.hostId) throw new t({ detail: "Lockstep terminal returned an unrelated SQL receipt" });
|
|
926
|
+
this.terminal.delete(i), this.rooms.delete(i), this.snapshotBudget.forget(i);
|
|
927
|
+
} catch (e) {
|
|
928
|
+
r.push(e);
|
|
929
|
+
}
|
|
930
|
+
else if (!this.pending.has(i)) {
|
|
931
|
+
if (!a.cleaned) {
|
|
932
|
+
let e = await this.retire(s, a.disposition === "hibernating");
|
|
933
|
+
if (e.length) {
|
|
934
|
+
r.push(...e);
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
a.cleaned = !0;
|
|
938
|
+
}
|
|
939
|
+
try {
|
|
940
|
+
a.disposition === "hibernating" ? a.staged ? this.capture(s, "hibernated", {
|
|
941
|
+
...a.staged,
|
|
942
|
+
commands: []
|
|
943
|
+
}) : a.staged = this.capture(s, "hibernating") : (this.capture(s, a.disposition), this.terminal.delete(i));
|
|
944
|
+
} catch (e) {
|
|
945
|
+
r.push(e);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return r;
|
|
950
|
+
}
|
|
951
|
+
async settleForDrain(e) {
|
|
952
|
+
if (this.closed || this.turning || this.drains.has(e) || this.heldPublication.has(e)) throw new t({ detail: "Retained lifecycle settlement requires exclusive pre-drain supervision" });
|
|
953
|
+
this.turning = !0;
|
|
954
|
+
try {
|
|
955
|
+
this.collectTerminal(), this.withdrawn.has(e) && await this.finishWithdrawal(e), await this.commitPending(e);
|
|
956
|
+
let n = await this.captureTerminal(e);
|
|
957
|
+
if (n.length) throw AggregateError(n, "Retained Room terminal work remains incomplete");
|
|
958
|
+
if (await this.commitPending(e), this.terminal.has(e) || this.pending.get(e)?.retire) throw this.isHibernating(e) ? new a({ roomId: e }) : new t({ detail: "Retained Room retirement requires another supervision pass" });
|
|
959
|
+
let r = this.rooms.get(e);
|
|
960
|
+
if (!r) return "retired";
|
|
961
|
+
if (r.mode === "lockstep") r.owner.isPublished() || await r.owner.publishAsync();
|
|
962
|
+
else if (r.lastCheckpointFingerprint === null) {
|
|
963
|
+
if (!r.checkpointReady()) throw new t({ detail: "Initial Room checkpoint awaits accepted lifecycle work" });
|
|
964
|
+
this.capture(r, "live"), await this.commitPending(e);
|
|
965
|
+
}
|
|
966
|
+
return "active";
|
|
967
|
+
} finally {
|
|
968
|
+
this.turning = !1;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
collectTerminal() {
|
|
972
|
+
let e = [...this.host.drainFaults().map((e) => ({
|
|
973
|
+
id: e.roomId,
|
|
974
|
+
disposition: "faulted"
|
|
975
|
+
})), ...this.host.takeRetired().map((e) => ({
|
|
976
|
+
id: e.id,
|
|
977
|
+
disposition: this.rooms.get(e.id)?.mode === "state-sync" && this.rooms.get(e.id).hibernateOnEmpty ? "hibernating" : "disposed"
|
|
978
|
+
}))];
|
|
979
|
+
for (let t of e) this.snapshotBudget.forget(t.id), this.terminal.set(t.id, {
|
|
980
|
+
disposition: t.disposition,
|
|
981
|
+
cleaned: !1,
|
|
982
|
+
staged: null
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
async turn() {
|
|
986
|
+
if (this.closed) throw new i({ roomId: "host" });
|
|
987
|
+
if (this.turning) throw new n({
|
|
988
|
+
room: "host",
|
|
989
|
+
detail: "Runtime turns cannot overlap"
|
|
990
|
+
});
|
|
991
|
+
this.turning = !0;
|
|
992
|
+
try {
|
|
993
|
+
for (let e of this.withdrawn.keys()) await this.finishWithdrawal(e);
|
|
994
|
+
await this.commitPending();
|
|
995
|
+
for (let [e, t] of this.rooms) t.mode === "state-sync" && !this.heldPublication.has(e) && !this.terminal.has(e) && !this.withdrawn.has(e) && !this.drains.has(e) && !this.pending.get(e)?.retire && await t.pumpGeometry();
|
|
996
|
+
let e = this.loopObservation.measure(() => this.host.advance((e) => !this.heldPublication.has(e))), t = [];
|
|
997
|
+
this.collectTerminal(), t.push(...await this.captureTerminal());
|
|
998
|
+
let r = this.host.activeRooms(), i = r.findIndex((e) => e.id === this.lastPeriodicRoom), a = i < 0 ? r : [...r.slice(i + 1), ...r.slice(0, i + 1)];
|
|
999
|
+
for (let e of a) {
|
|
1000
|
+
let r = this.rooms.get(e.id);
|
|
1001
|
+
if (!r) throw new n({
|
|
1002
|
+
room: e.id,
|
|
1003
|
+
detail: "Host contains an unowned room"
|
|
1004
|
+
});
|
|
1005
|
+
if (this.heldPublication.has(e.id)) continue;
|
|
1006
|
+
if (r.mode === "lockstep") {
|
|
1007
|
+
try {
|
|
1008
|
+
await r.owner.maintenance();
|
|
1009
|
+
for (let e of r.sessions) e.teardownReady() && r.sessions.delete(e);
|
|
1010
|
+
await r.owner.flush();
|
|
1011
|
+
} catch (e) {
|
|
1012
|
+
t.push(e);
|
|
1013
|
+
}
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
let i = !1;
|
|
1017
|
+
for (let e of r.sessions) if (e.maintenance(), e.teardownReady()) try {
|
|
1018
|
+
await e.settled(), r.sessions.delete(e);
|
|
1019
|
+
} catch (e) {
|
|
1020
|
+
t.push(e), i = !0;
|
|
1021
|
+
}
|
|
1022
|
+
if (i || !r.checkpointReady()) continue;
|
|
1023
|
+
try {
|
|
1024
|
+
r.flush();
|
|
1025
|
+
} catch (e) {
|
|
1026
|
+
t.push(e);
|
|
1027
|
+
}
|
|
1028
|
+
let a = this.clock.now();
|
|
1029
|
+
if (a >= r.nextSendAt) {
|
|
1030
|
+
r.produceSpectators();
|
|
1031
|
+
for (let e of r.sessions) e.publishState();
|
|
1032
|
+
r.nextSendAt = a + r.sendInterval;
|
|
1033
|
+
}
|
|
1034
|
+
if (!r.checkpointReady()) continue;
|
|
1035
|
+
let o = r.listing(), s = r.hasCommands() || o !== void 0 && m(o) !== r.lastListing;
|
|
1036
|
+
if (!s && a < r.nextSnapshotAt || !s && this.snapshotBudget.blocked(r.id)) continue;
|
|
1037
|
+
let c = r.capture();
|
|
1038
|
+
!s && c.commands.length === 0 && r.onlyIfChanged && r.lastCheckpointFingerprint === U(c) ? (r.nextSnapshotAt = a + r.snapshotEveryMs, this.unchangedSnapshotsSkipped++, this.snapshotBudget.forget(r.id)) : s || c.commands.length ? this.capture(r, "live", c) : this.capture(r, "live", c, !0) && (this.lastPeriodicRoom = r.id);
|
|
1039
|
+
}
|
|
1040
|
+
try {
|
|
1041
|
+
await this.commitPending();
|
|
1042
|
+
} catch (e) {
|
|
1043
|
+
t.push(e);
|
|
1044
|
+
}
|
|
1045
|
+
if (t.length) throw AggregateError(t, "Room supervision failed");
|
|
1046
|
+
return e;
|
|
1047
|
+
} finally {
|
|
1048
|
+
this.turning = !1;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
async close() {
|
|
1052
|
+
if (this.heldPublication.size) throw new t({ detail: "Held publication must finish or lose ownership before terminal close" });
|
|
1053
|
+
if (this.drains.size) throw new t({ detail: "Prepared drain ownership must be handed off and withdrawn before terminal close" });
|
|
1054
|
+
if (this.turning) throw new n({
|
|
1055
|
+
room: "host",
|
|
1056
|
+
detail: "Await the current turn before shutdown"
|
|
1057
|
+
});
|
|
1058
|
+
this.turning = !0, this.closed = !0;
|
|
1059
|
+
try {
|
|
1060
|
+
for (let e of this.withdrawn.keys()) await this.finishWithdrawal(e);
|
|
1061
|
+
await this.commitPending();
|
|
1062
|
+
let e = [];
|
|
1063
|
+
for (let e of this.host.takeAll()) this.terminal.set(e.id, {
|
|
1064
|
+
disposition: "disposed",
|
|
1065
|
+
cleaned: !1,
|
|
1066
|
+
staged: null
|
|
1067
|
+
});
|
|
1068
|
+
e.push(...await this.captureTerminal());
|
|
1069
|
+
try {
|
|
1070
|
+
await this.commitPending();
|
|
1071
|
+
} catch (t) {
|
|
1072
|
+
e.push(t);
|
|
1073
|
+
}
|
|
1074
|
+
if (e.length) throw AggregateError(e, "Room runtime shutdown failed");
|
|
1075
|
+
let t = [...this.terminal.keys()][0];
|
|
1076
|
+
if (t !== void 0) throw new a({ roomId: t });
|
|
1077
|
+
} finally {
|
|
1078
|
+
this.turning = !1;
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
retains(e) {
|
|
1082
|
+
return this.rooms.has(e);
|
|
1083
|
+
}
|
|
1084
|
+
isHibernating(e) {
|
|
1085
|
+
return this.terminal.get(e)?.disposition === "hibernating";
|
|
1086
|
+
}
|
|
1087
|
+
hasPendingCheckpoint(e) {
|
|
1088
|
+
return this.pending.has(e);
|
|
1089
|
+
}
|
|
1090
|
+
metrics() {
|
|
1091
|
+
let e = 0, t = 0, n = 0, r = 0, i = null, a = 0;
|
|
1092
|
+
for (let o of this.rooms.values()) {
|
|
1093
|
+
e += o.sessions.size;
|
|
1094
|
+
for (let e of o.sessions) {
|
|
1095
|
+
let o = e.reportedLoss?.() ?? null;
|
|
1096
|
+
o !== null && (i = Math.max(i ?? 0, o), o >= 100 && a++), r += e.staleInputs?.() ?? 0;
|
|
1097
|
+
let s = e.sendThrottle?.();
|
|
1098
|
+
s && (s.level > 0 && t++, n += s.throttles);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
let o = this.snapshotBudget.metrics();
|
|
1102
|
+
return {
|
|
1103
|
+
loop: this.loopObservation.snapshot(),
|
|
1104
|
+
ownedRooms: this.rooms.size,
|
|
1105
|
+
pendingCheckpoints: this.pending.size,
|
|
1106
|
+
sessions: e,
|
|
1107
|
+
checkpointCommits: this.checkpointCommits,
|
|
1108
|
+
checkpointStateBytes: this.checkpointStateBytes,
|
|
1109
|
+
unchangedSnapshotsSkipped: this.unchangedSnapshotsSkipped,
|
|
1110
|
+
snapshotDeferred: o.deferred,
|
|
1111
|
+
snapshotForcedBytes: o.forcedBytes,
|
|
1112
|
+
snapshotPeriodicBytes: o.periodicBytes,
|
|
1113
|
+
snapshotDebtBytes: o.debtBytes,
|
|
1114
|
+
throttledSessions: t,
|
|
1115
|
+
clientThrottles: n,
|
|
1116
|
+
staleInputsDropped: r,
|
|
1117
|
+
maxReportedLossPermille: i,
|
|
1118
|
+
lossySessions: a
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
//#endregion
|
|
1123
|
+
export { G as RoomRuntime };
|