@3dsource/angular-unreal-module 0.0.146-dev.4 → 0.0.146-dev.5
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.
|
@@ -1670,6 +1670,10 @@ class RegionsPingService {
|
|
|
1670
1670
|
* entry is well-formed and still within {@link REGION_PING_CACHE_TTL_MS}.
|
|
1671
1671
|
* All access is guarded — `localStorage` can throw (private mode, disabled
|
|
1672
1672
|
* storage) or be absent (non-browser).
|
|
1673
|
+
*
|
|
1674
|
+
* Public so adopted connections (which skip `getFastest`) can replay the
|
|
1675
|
+
* region-resolving telemetry phase from the same cached winner — see
|
|
1676
|
+
* `UnrealEffects.regionTelemetryOnAdopt$`.
|
|
1673
1677
|
*/
|
|
1674
1678
|
readCachedWinner() {
|
|
1675
1679
|
try {
|
|
@@ -3598,14 +3602,19 @@ class StreamAdoptionService {
|
|
|
3598
3602
|
*
|
|
3599
3603
|
* - nothing parked → emit `false` at once (caller connects normally).
|
|
3600
3604
|
* - already settled (`ready`/`failed`/`adopted`) → adopt-if-ready at once.
|
|
3601
|
-
* - still `connecting` → poll until
|
|
3602
|
-
* by `timeoutMs` so a stuck prefetch can't block the fallback forever.
|
|
3605
|
+
* - still `connecting` → poll until the script settles it, then adopt-if-ready.
|
|
3603
3606
|
*
|
|
3604
|
-
*
|
|
3605
|
-
*
|
|
3606
|
-
*
|
|
3607
|
+
* Deliberately NO time budget: for DIRECT orchestration the prefetch holds
|
|
3608
|
+
* the socket open while the orchestrator provisions a machine, which can take
|
|
3609
|
+
* minutes (150–200s+). A fixed deadline would make Angular give up and open a
|
|
3610
|
+
* second connection mid-provisioning — exactly the race/orphan this avoids.
|
|
3611
|
+
* The wait is bounded by liveness instead: the script flips the parked state
|
|
3612
|
+
* to `failed` on a dead socket (`ws.onclose`/`onerror`), and the caller wraps
|
|
3613
|
+
* this in `takeUntil(abortEstablishingConnection)`, so a route change / teardown
|
|
3614
|
+
* cancels it. Emits exactly once. Cancelling runs no adoption — which is what
|
|
3615
|
+
* stops a fast route-switch from starting overlapping connections.
|
|
3607
3616
|
*/
|
|
3608
|
-
awaitAndAdopt$(
|
|
3617
|
+
awaitAndAdopt$() {
|
|
3609
3618
|
const parked = window.__stream;
|
|
3610
3619
|
if (!parked) {
|
|
3611
3620
|
return of(false);
|
|
@@ -3615,9 +3624,9 @@ class StreamAdoptionService {
|
|
|
3615
3624
|
}
|
|
3616
3625
|
Logger.info('[Adoption] Prefetch in progress — waiting before connecting');
|
|
3617
3626
|
return timer(0, ADOPT_POLL_MS).pipe(map$1(() => window.__stream?.state ?? 'failed'),
|
|
3618
|
-
// Keep polling while still connecting
|
|
3619
|
-
//
|
|
3620
|
-
takeWhile((state
|
|
3627
|
+
// Keep polling while still connecting; the `true` (inclusive) emits the
|
|
3628
|
+
// settling value (`ready`/`failed`) that ends the wait.
|
|
3629
|
+
takeWhile((state) => state === 'connecting', true), last(), map$1(() => this.tryAdopt()));
|
|
3621
3630
|
}
|
|
3622
3631
|
/**
|
|
3623
3632
|
* @returns `true` if a ready parked stream was adopted (caller must NOT
|
|
@@ -4197,9 +4206,7 @@ class UnrealEffects {
|
|
|
4197
4206
|
// connection; otherwise fall back to a fresh signalling connection.
|
|
4198
4207
|
// `takeUntil(abort)` cancels the wait on teardown / route change so a
|
|
4199
4208
|
// fast switch can't leave overlapping connections.
|
|
4200
|
-
this.streamAdoptionService
|
|
4201
|
-
.awaitAndAdopt$(this.dataChannelConnectionTimeout)
|
|
4202
|
-
.pipe(switchMap((adopted) => adopted ? EMPTY : this.signallingService.connectToSignaling(urls)), takeUntil(this.actions$.pipe(ofType(abortEstablishingConnection))),
|
|
4209
|
+
this.streamAdoptionService.awaitAndAdopt$().pipe(switchMap((adopted) => adopted ? EMPTY : this.signallingService.connectToSignaling(urls)), takeUntil(this.actions$.pipe(ofType(abortEstablishingConnection))),
|
|
4203
4210
|
// The adopt/connect stream is side-effect-only (its values aren't
|
|
4204
4211
|
// actions) — swallow them, and emit `setEstablishingConnection`
|
|
4205
4212
|
// first so the reconnect/resume popup stays hidden during the
|
|
@@ -4207,6 +4214,24 @@ class UnrealEffects {
|
|
|
4207
4214
|
// defers `connectToSignaling`, which is what normally sets this.
|
|
4208
4215
|
ignoreElements(), startWith(setEstablishingConnection({ value: true })))));
|
|
4209
4216
|
});
|
|
4217
|
+
// Adoption skips `connectToSignaling → getRegion`, so the region-resolving
|
|
4218
|
+
// telemetry phase never fires. Replay the region waterfall (start → end →
|
|
4219
|
+
// resolved) from the cached winner the prefetch reused — a near-zero-length
|
|
4220
|
+
// phase that still carries the ping samples. No live ping sweep; if there is
|
|
4221
|
+
// no cache the resolved event just carries empty values.
|
|
4222
|
+
this.regionTelemetryOnAdopt$ = createEffect(() => {
|
|
4223
|
+
return this.actions$.pipe(ofType(streamAdopted), mergeMap(() => {
|
|
4224
|
+
const cached = this.regionsPingService.readCachedWinner();
|
|
4225
|
+
return [
|
|
4226
|
+
regionPingFetchStart(),
|
|
4227
|
+
regionPingFetchEnd(),
|
|
4228
|
+
regionResolved({
|
|
4229
|
+
region: cached?.region_code ?? '',
|
|
4230
|
+
pingsMs: cached?.result ?? [],
|
|
4231
|
+
}),
|
|
4232
|
+
];
|
|
4233
|
+
}));
|
|
4234
|
+
});
|
|
4210
4235
|
}
|
|
4211
4236
|
canPeerReconnect() {
|
|
4212
4237
|
return RECONNECT_CONFIG.enabled && this.signallingService.isConnected();
|
|
@@ -5615,17 +5640,13 @@ class StreamStatusTelemetryService2 {
|
|
|
5615
5640
|
// CLOSER — the `regionResolved` action carries the raw ping
|
|
5616
5641
|
// samples (one per probe) from `RegionsPingService`; the
|
|
5617
5642
|
// catalog flattens them to a comma-separated string since
|
|
5618
|
-
// `toPhaseParams` only accepts primitives.
|
|
5619
|
-
//
|
|
5620
|
-
//
|
|
5621
|
-
//
|
|
5622
|
-
// using the cached ping result the prefetch reused, so the region
|
|
5623
|
-
// phase still appears (with its ping samples). Because this fires at
|
|
5624
|
-
// adoption time it also re-anchors `lastMilestonePerf`, which keeps the
|
|
5625
|
-
// following signaling / webrtc phases at ~0 for adopted sessions.
|
|
5643
|
+
// `toPhaseParams` only accepts primitives. Adopted connections never
|
|
5644
|
+
// run `getRegion`, but `UnrealEffects.regionTelemetryOnAdopt$` replays
|
|
5645
|
+
// the region waterfall (start → end → resolved) from the cached winner,
|
|
5646
|
+
// so this phase still appears with its ping samples.
|
|
5626
5647
|
{
|
|
5627
5648
|
id: 'region-resolved',
|
|
5628
|
-
event:
|
|
5649
|
+
event: this.actions$.pipe(ofType(regionResolved), take(1), map(({ region, pingsMs }) => ({
|
|
5629
5650
|
region,
|
|
5630
5651
|
pingsMs: pingsMs.length ? `${pingsMs.join(', ')} ms` : null,
|
|
5631
5652
|
}))),
|
|
@@ -5786,29 +5807,6 @@ class StreamStatusTelemetryService2 {
|
|
|
5786
5807
|
return v4();
|
|
5787
5808
|
}
|
|
5788
5809
|
}
|
|
5789
|
-
/**
|
|
5790
|
-
* Region winner + ping samples cached in `localStorage` by
|
|
5791
|
-
* `region-ping-prefetch.js` / `RegionsPingService` (`REGION_PING_CACHE_KEY`).
|
|
5792
|
-
* Used to fill the region phase for ADOPTED connections, which never run
|
|
5793
|
-
* `getRegion()` and so never dispatch `regionResolved`. Empty when there is
|
|
5794
|
-
* no usable cache.
|
|
5795
|
-
*/
|
|
5796
|
-
cachedRegionResult() {
|
|
5797
|
-
try {
|
|
5798
|
-
const raw = localStorage.getItem(REGION_PING_CACHE_KEY);
|
|
5799
|
-
const parsed = raw ? JSON.parse(raw) : null;
|
|
5800
|
-
if (parsed && typeof parsed.region_code === 'string') {
|
|
5801
|
-
return {
|
|
5802
|
-
region: parsed.region_code,
|
|
5803
|
-
pingsMs: Array.isArray(parsed.result) ? parsed.result : [],
|
|
5804
|
-
};
|
|
5805
|
-
}
|
|
5806
|
-
}
|
|
5807
|
-
catch {
|
|
5808
|
-
/* ignore — best-effort */
|
|
5809
|
-
}
|
|
5810
|
-
return { region: '', pingsMs: [] };
|
|
5811
|
-
}
|
|
5812
5810
|
init() {
|
|
5813
5811
|
// Start a new session when a real connection attempt BEGINS, not on
|
|
5814
5812
|
// every `initSignalling` dispatch. `initSignalling` is fired multiple
|