| ... | ... | @@ -2839,6 +2839,73 @@ it.effect("ProviderSessionManagerV2 releases pinned idle sessions once the pin c |
| 2839 | 2839 | }), |
| 2840 | 2840 | ); |
| 2841 | 2841 | |
| 2842 | it.effect("ProviderSessionManagerV2 keeps pinned work that reports progress", () => |
| 2843 | Effect.gen(function* () { |
| 2844 | const state = yield* Ref.make(emptyState); |
| 2845 | const effect = Effect.gen(function* () { |
| 2846 | const eventSink = yield* EventSink.EventSinkV2; |
| 2847 | const idAllocator = yield* IdAllocator.IdAllocatorV2; |
| 2848 | const manager = yield* ProviderSessionManager.ProviderSessionManagerV2; |
| 2849 | const now = yield* DateTime.now; |
| 2850 | const threadId = yield* idAllocator.allocate.thread({ |
| 2851 | fixtureName: "provider-session-manager-pin-progress", |
| 2852 | projectId: yield* idAllocator.allocate.project({ |
| 2853 | fixtureName: "provider-session-manager-pin-progress", |
| 2854 | }), |
| 2855 | }); |
| 2856 | const providerSessionId = yield* idAllocator.allocate.providerSession({ |
| 2857 | providerInstanceId: modelSelection.instanceId, |
| 2858 | threadId, |
| 2859 | }); |
| 2860 | yield* eventSink.write({ |
| 2861 | events: [yield* makeThreadCreatedEvent({ idAllocator, threadId, now })], |
| 2862 | }); |
| 2863 | const runtime = yield* manager.open({ |
| 2864 | threadId, |
| 2865 | providerSessionId, |
| 2866 | modelSelection, |
| 2867 | runtimePolicy, |
| 2868 | }); |
| 2869 | const adapterQueue = (yield* Ref.get(state)).eventQueues.get(String(providerSessionId)); |
| 2870 | assert.isDefined(adapterQueue); |
| 2871 | const step = (duration: Parameters<typeof TestClock.adjust>[0]) => |
| 2872 | Effect.gen(function* () { |
| 2873 | yield* TestClock.adjust(duration); |
| 2874 | for (let i = 0; i < 20; i += 1) yield* Effect.yieldNow; |
| 2875 | }); |
| 2876 | |
| 2877 | // A long workflow keeps reporting progress well past the pin cap. |
| 2878 | for (let tick = 0; tick < 12; tick += 1) { |
| 2879 | yield* step("1500 millis"); |
| 2880 | yield* Queue.offer(adapterQueue!, { |
| 2881 | type: "provider_session.updated", |
| 2882 | driver: CODEX_DRIVER, |
| 2883 | providerSession: runtime.providerSession, |
| 2884 | }); |
| 2885 | for (let i = 0; i < 20; i += 1) yield* Effect.yieldNow; |
| 2886 | } |
| 2887 | assert.equal((yield* Ref.get(state)).closeCount, 0); |
| 2888 | |
| 2889 | // Work that goes silent past the cap is still stopped. |
| 2890 | for (let tick = 0; tick < 6; tick += 1) { |
| 2891 | yield* step("1 second"); |
| 2892 | } |
| 2893 | assert.equal((yield* Ref.get(state)).closeCount, 1); |
| 2894 | }); |
| 2895 | |
| 2896 | yield* effect.pipe( |
| 2897 | Effect.provide( |
| 2898 | layerTest({ |
| 2899 | state, |
| 2900 | idleTimeoutMs: 1000, |
| 2901 | maxIdlePinMs: 3000, |
| 2902 | hasPendingBackgroundWork: Effect.succeed(true), |
| 2903 | }), |
| 2904 | ), |
| 2905 | ); |
| 2906 | }), |
| 2907 | ); |
| 2908 | |
| 2842 | 2909 | it.effect( |
| 2843 | 2910 | "ProviderSessionManagerV2 does not idle-release a session that turns busy during the pending-work check", |
| 2844 | 2911 | () => |