Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions apps/mobile/src/connection/environment-cache-store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ConnectionPersistenceError,
EnvironmentCacheStore,
encodeShellSnapshotForCache,
} from "@t3tools/client-runtime/platform";
import {
type EnvironmentId,
Expand Down Expand Up @@ -56,7 +57,6 @@ const StoredVcsRefs = Schema.Struct({
const decodeStoredShellSnapshot = Schema.decodeUnknownEffect(
Schema.fromJsonString(StoredShellSnapshot),
);
const encodeStoredShellSnapshot = Schema.encodeEffect(Schema.fromJsonString(StoredShellSnapshot));
const decodeStoredThreadSnapshot = Schema.decodeUnknownEffect(
Schema.fromJsonString(StoredThreadSnapshot),
);
Expand Down Expand Up @@ -136,11 +136,18 @@ export const make = Effect.fn("MobileEnvironmentCacheStore.make")(function* () {
}).pipe(Effect.tap(() => Effect.promise(() => projectFaviconDatabaseCache.hydrate()))),
),
saveShell: Effect.fn("MobileEnvironmentCache.saveShell")(function* (environmentId, snapshot) {
const payload = yield* encodeStoredShellSnapshot({
schemaVersion: SHELL_SNAPSHOT_CACHE_SCHEMA_VERSION,
environmentId,
snapshot,
}).pipe(Effect.mapError((cause) => persistenceError("save-shell", cause)));
const encodedSnapshot = yield* encodeShellSnapshotForCache(snapshot).pipe(
Effect.mapError((cause) => persistenceError("save-shell", cause)),
);
const payload = yield* Effect.try({
try: () =>
JSON.stringify({
schemaVersion: SHELL_SNAPSHOT_CACHE_SCHEMA_VERSION,
environmentId,
snapshot: encodedSnapshot,
} satisfies typeof StoredShellSnapshot.Encoded),
catch: (cause) => persistenceError("save-shell", cause),
});
yield* database
.saveCache(environmentId, "shell", "snapshot", SHELL_SNAPSHOT_CACHE_SCHEMA_VERSION, payload)
.pipe(Effect.mapError(mapDatabaseError("save-shell")));
Expand Down
7 changes: 2 additions & 5 deletions apps/mobile/src/features/threads/threadListV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
sortActiveThreadsByOrderKey,
resolveSettledThreadTimestamp,
sortPinnedThreadsByOrderKey,
sortSettledThreads,
} from "@t3tools/client-runtime/state/thread-sort";
import type { EnvironmentId, ProjectId } from "@t3tools/contracts";

Expand Down Expand Up @@ -606,11 +607,7 @@ export function buildThreadListV2Items(input: {
: orderedSnoozed.filter(
(thread) => `${thread.environmentId}:${thread.id}` === selectedThreadKey,
);
const orderedSettled = [...settled].sort(
(left, right) =>
parseTimestampMs(resolveSettledThreadTimestamp(right) ?? "") -
parseTimestampMs(resolveSettledThreadTimestamp(left) ?? ""),
);
const orderedSettled = sortSettledThreads(settled);
const settledLimit = input.settledLimit ?? Number.POSITIVE_INFINITY;
const pagedSettled =
orderedSettled.length > settledLimit ? orderedSettled.slice(0, settledLimit) : orderedSettled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ export const makeOrchestrationIntegrationHarness = (
Layer.provideMerge(
Layer.succeed(AgentAwarenessRelay.AgentAwarenessRelay, {
publishThread: () => Effect.void,
requestCatchUp: () => Effect.void,
start: () => Effect.void,
}),
),
Expand Down
23 changes: 2 additions & 21 deletions apps/server/src/cli/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Option from "effect/Option";
import * as Schema from "effect/Schema";
import * as Stream from "effect/Stream";
import { Command, Flag } from "effect/unstable/cli";

import * as ServerConfig from "../config.ts";
import { toRotatedTracePaths, TraceFileReadError } from "../diagnostics/TraceDiagnostics.ts";
import { streamTraceFileLines, toRotatedTracePaths } from "../diagnostics/TraceDiagnostics.ts";
import { resolveBaseDir } from "../os-jank.ts";
import { baseDirFlag, DurationFromString, traceFileConfig, traceMaxFilesConfig } from "./config.ts";

Expand Down Expand Up @@ -187,27 +186,9 @@ const traceSummaryCommand = Command.make("summary", {
? (yield* Clock.currentTimeMillis) - Duration.toMillis(flags.since.value)
: undefined;
const summarizer = makeTraceSpanSummary(sinceMs);
// Stream each file so only one chunk of text is in memory at a time.
yield* Effect.forEach(
toRotatedTracePaths(traceFilePath, yield* traceMaxFilesConfig),
(path) =>
fs.stream(path).pipe(
Stream.decodeText,
Stream.splitLines,
Stream.runForEachArray((lines) => Effect.sync(() => lines.forEach(summarizer.addLine))),
Effect.catchTags({
PlatformError: (cause) =>
cause.reason._tag === "NotFound"
? Effect.void
: Effect.fail(
new TraceFileReadError({
traceFilePath: path,
causeTag: cause.reason._tag,
cause,
}),
),
}),
),
(path) => streamTraceFileLines(fs, path, summarizer.addLine),
{ discard: true },
);
const summary = summarizer.finish();
Expand Down
9 changes: 9 additions & 0 deletions apps/server/src/cloud/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
type ServiceUpdateRecord,
} from "./serviceProtocol.ts";
import * as ServerEnvironment from "../environment/ServerEnvironment.ts";
import * as AgentAwarenessRelay from "../relay/AgentAwarenessRelay.ts";
import { CLOUD_CLI_DESIRED_LINK_SECRET } from "./CliState.ts";
import * as CliTokenManager from "./CliTokenManager.ts";
import {
Expand Down Expand Up @@ -81,6 +82,12 @@ const storeFailure = (tag: "AlreadyExists" | "PermissionDenied") =>
});

const unusedSecretStoreOperation = () => Effect.die("unused secret-store operation");
// Linking wakes the awareness relay; these tests do not run it.
const idleAwarenessRelay = AgentAwarenessRelay.AgentAwarenessRelay.of({
publishThread: () => Effect.void,
requestCatchUp: () => Effect.void,
start: () => Effect.void,
});
const decodeManagedTunnelRecoveryRegistration = Schema.decodeUnknownEffect(
Schema.fromJsonString(RelayManagedEndpointRecoveryRegistrationRequest),
);
Expand Down Expand Up @@ -262,6 +269,7 @@ describe("reconcileDesiredCloudLink", () => {
HttpClient.HttpClient,
HttpClient.make(() => unusedSecretStoreOperation()),
),
Effect.provideService(AgentAwarenessRelay.AgentAwarenessRelay, idleAwarenessRelay),
Effect.provide(NodeServices.layer),
),
);
Expand Down Expand Up @@ -375,6 +383,7 @@ describe("releaseManagedTunnelOnShutdown", () => {
<A, E, R>(effect: Effect.Effect<A, E, R>) =>
effect.pipe(
Effect.provideService(ServerSecretStore.ServerSecretStore, harness.store),
Effect.provideService(AgentAwarenessRelay.AgentAwarenessRelay, idleAwarenessRelay),
Effect.provideService(
ServerEnvironment.ServerEnvironment,
ServerEnvironment.ServerEnvironment.of({
Expand Down
5 changes: 5 additions & 0 deletions apps/server/src/cloud/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import * as ServerSecretStore from "../auth/ServerSecretStore.ts";
import { requireEnvironmentScope } from "../auth/http.ts";
import * as ServerConfig from "../config.ts";
import * as ServerEnvironment from "../environment/ServerEnvironment.ts";
import * as AgentAwarenessRelay from "../relay/AgentAwarenessRelay.ts";
import * as ManagedEndpointRuntime from "./ManagedEndpointRuntime.ts";
import {
SERVICE_STATE_FILE,
Expand Down Expand Up @@ -411,6 +412,7 @@ interface CloudHttpDependencies {
readonly environmentAuth: EnvironmentAuth.EnvironmentAuth["Service"];
readonly cliTokenManager: CliTokenManager.CloudCliTokenManager["Service"];
readonly httpClient: HttpClient.HttpClient;
readonly awarenessRelay: AgentAwarenessRelay.AgentAwarenessRelay["Service"];
}

const cloudHttpDependencies = Effect.gen(function* () {
Expand All @@ -421,6 +423,7 @@ const cloudHttpDependencies = Effect.gen(function* () {
environmentAuth: yield* EnvironmentAuth.EnvironmentAuth,
cliTokenManager: yield* CliTokenManager.CloudCliTokenManager,
httpClient: yield* HttpClient.HttpClient,
awarenessRelay: yield* AgentAwarenessRelay.AgentAwarenessRelay,
} satisfies CloudHttpDependencies;
});

Expand Down Expand Up @@ -668,6 +671,7 @@ const applyCloudRelayConfig = Effect.fn("environment.cloud.applyRelayConfig")(fu
CLOUD_MINT_PUBLIC_KEY,
stringToBytes(payload.cloudMintPublicKey),
);
yield* dependencies.awarenessRelay.requestCatchUp();
if (payload.endpointRuntime) {
const endpointRuntimeJson = yield* encodeEndpointRuntimeConfigJson(payload.endpointRuntime);
yield* dependencies.secrets.set(
Expand Down Expand Up @@ -1349,6 +1353,7 @@ const cloudPreferencesHandler = Effect.fn("environment.cloud.preferences")(
PUBLISH_AGENT_ACTIVITY_SECRET,
stringToBytes(String(payload.publishAgentActivity)),
);
yield* dependencies.awarenessRelay.requestCatchUp();
return yield* readCloudLinkState(dependencies);
},
Effect.catchIf(
Expand Down
Loading
Loading