Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
412 changes: 412 additions & 0 deletions packages/realm-server/handlers/create-realm.ts

Large diffs are not rendered by default.

181 changes: 0 additions & 181 deletions packages/realm-server/handlers/handle-create-realm.ts

This file was deleted.

37 changes: 37 additions & 0 deletions packages/realm-server/handlers/send-event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { DBAdapter } from '@cardstack/runtime-common';
import { fetchSessionRoom } from '@cardstack/runtime-common';
import type { MatrixClient } from '@cardstack/runtime-common/matrix-client';
import { APP_BOXEL_REALM_SERVER_EVENT_MSGTYPE } from '@cardstack/runtime-common/matrix-constants';

export type SendEventDeps = {
matrixClient: MatrixClient;
dbAdapter: DBAdapter;
};

export type SendEvent = (
user: string,
eventType: string,
data?: Record<string, any>,
) => Promise<void>;

export function createSendEvent({
matrixClient,
dbAdapter,
}: SendEventDeps): SendEvent {
return async function sendEvent(user, eventType, data) {
if (!matrixClient.isLoggedIn()) {
await matrixClient.login();
}
let roomId = await fetchSessionRoom(dbAdapter, user);
if (!roomId) {
console.error(
`Failed to send event: ${eventType}, cannot find session room for user: ${user}`,
);
}

await matrixClient.sendEvent(roomId!, 'm.room.message', {
Comment thread
habdelra marked this conversation as resolved.
body: JSON.stringify({ eventType, data }),
msgtype: APP_BOXEL_REALM_SERVER_EVENT_MSGTYPE,
});
};
}
66 changes: 66 additions & 0 deletions packages/realm-server/handlers/serve-from-realm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type Koa from 'koa';
import type {
DBAdapter,
Realm,
VirtualNetwork,
} from '@cardstack/runtime-common';
import { logger } from '@cardstack/runtime-common';
import { fetchRequestFromContext, setContextResponse } from '../middleware';
import { setupCloseHandler } from '../node-realm';
import { findOrMountRealm } from '../lib/realm-routing';
import type { RealmRegistryReconciler } from '../lib/realm-registry-reconciler';

export type ServeFromRealmDeps = {
realms: Realm[];
reconciler: RealmRegistryReconciler;
dbAdapter: DBAdapter;
virtualNetwork: VirtualNetwork;
};

const log = logger('realm-server');

export function createServeFromRealm(
deps: ServeFromRealmDeps,
): (ctxt: Koa.Context, next: Koa.Next) => Promise<void> {
let { virtualNetwork } = deps;
return async function serveFromRealm(ctxt: Koa.Context, _next: Koa.Next) {
if (ctxt.request.path === '/_boom') {
throw new Error('boom');
}
let request = await fetchRequestFromContext(ctxt);
// Phase 3 lazy mount: trigger findOrMountRealm before dispatching to
// virtualNetwork.handle so non-pinned realms (source/published) mount
// on first request. virtualNetwork.handle returns 404 for any URL
// whose handle isn't registered, which is exactly what happens for
// a realm that the reconciler knows about (knownByUrl) but hasn't
// mounted yet. findOrMountRealm walks knownByUrl, calls
// reconciler.lookupOrMount() on a prefix match, and that
// synchronously publishes the realm into virtualNetwork before the
// dispatch below. Mount failures throw — the catch turns them into
// 503 so the next request retries from scratch (ensureMounted's
// failure path clears mounted/pendingMounts).
let requestURL = new URL(
`${ctxt.protocol}://${ctxt.host}${ctxt.originalUrl}`,
);
try {
await findOrMountRealm(requestURL, deps);
} catch (err: any) {
log.warn(
`failed to mount realm for request ${requestURL.href}: ${err?.message ?? err}`,
);
ctxt.status = 503;
ctxt.body = `Realm mount failed: ${err?.message ?? err}`;
return;
}
let realmResponse = await virtualNetwork.handle(
request,
(mappedRequest) => {
// Setup this handler only after the request has been mapped because
// the *mapped request* is the one that gets closed, not the original one
setupCloseHandler(ctxt.res, mappedRequest);
},
);

await setContextResponse(ctxt, realmResponse);
};
}
Loading
Loading