Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move SSE to Matrix #2116

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
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
20 changes: 20 additions & 0 deletions packages/host/app/services/matrix-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ import type CommandService from './command-service';
import type LoaderService from './loader-service';
import type MatrixSDKLoader from './matrix-sdk-loader';
import type { ExtendedClient, ExtendedMatrixSDK } from './matrix-sdk-loader';
import type MessageService from './message-service';
import type RealmService from './realm';
import type RealmServerService from './realm-server';
import type ResetService from './reset';
Expand All @@ -110,6 +111,7 @@ export default class MatrixService extends Service {
@service private declare commandService: CommandService;
@service private declare realm: RealmService;
@service private declare matrixSdkLoader: MatrixSDKLoader;
@service private declare messageService: MessageService;
@service private declare realmServer: RealmServerService;
@service private declare router: RouterService;
@service private declare reset: ResetService;
Expand Down Expand Up @@ -1313,6 +1315,24 @@ export default class MatrixService extends Service {
event.content?.msgtype === APP_BOXEL_REALM_SERVER_EVENT_MSGTYPE
) {
await this.realmServer.handleEvent(event);
} else if (
event.type === 'm.room.message' &&
event.content?.msgtype === 'app.boxel.sse'
) {
// FIXME provenance should be checked
console.log('received sse event', event);
let parsedEventContent = JSON.parse(event.content.body);
console.log('relayMatrixSSE', parsedEventContent);

let realmInfoForSender = this.realm.realmOfMatrixUsername(event.sender);
if (!realmInfoForSender) {
console.log('ignoring sse event because no realm found', event);
} else {
this.messageService.relayMatrixSSE(
realmInfoForSender.url,
parsedEventContent,
);
}
}
await this.addRoomEvent(event, oldEventId);

Expand Down
29 changes: 25 additions & 4 deletions packages/host/app/services/message-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ import type NetworkService from './network';

export default class MessageService extends Service {
@tracked subscriptions: Map<string, EventSource> = new Map();
@tracked listenerCallbacks: Map<string, ((ev: ServerEvents) => void)[]> =
new Map();
@service private declare network: NetworkService;

register() {
(globalThis as any)._CARDSTACK_REALM_SUBSCRIBE = this;
}

subscribe(realmURL: string, cb: (ev: MessageEvent) => void): () => void {
console.log('subscribe', realmURL, cb);
if (isTesting()) {
// we don't have a way of dealing with internal testing realm URLs when
// creating an EventSource. The EventSource API is a native browser API
// that will try to issue a network request for our testing realm URLs
// otherwise.
// only use Matrix-y callbacks in testing
if (!this.listenerCallbacks.has(realmURL)) {
this.listenerCallbacks.set(realmURL, []);
}
this.listenerCallbacks.get(realmURL)?.push(cb);
return () => {};
}

Expand All @@ -48,13 +52,30 @@ export default class MessageService extends Service {
// TODO might want to consider making separate subscription methods so that
// you can subscribe to a specific type of events instead of all of the
// events...

if (!this.listenerCallbacks.has(realmURL)) {
this.listenerCallbacks.set(realmURL, []);
}
this.listenerCallbacks.get(realmURL)?.push(cb);

eventSource.addEventListener('update', cb);
eventSource.addEventListener('index', cb);
return () => {
eventSource.removeEventListener('update', cb);
eventSource.removeEventListener('index', cb);
};
}

relayMatrixSSE(realmURL: string, event: any) {
console.log('relaying matrix sse event', realmURL, event);
this.listenerCallbacks.get(realmURL)?.forEach((cb) => {
let eventWithStringData = {
type: event.type,
data: JSON.stringify(event.data),
};
cb(eventWithStringData);
});
}
}

function getPersistedTokenForRealm(realmURL: string) {
Expand Down
13 changes: 13 additions & 0 deletions packages/host/app/services/realm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,19 @@ export default class RealmService extends Service {
return undefined;
}

realmOfMatrixUsername(username: string) {
console.log(
'all realm usernames ',
Array.from(this.realms.values()).map((r) => r.info?.realmUserId),
);
let realm = Array.from(this.realms.values()).find(
(r) => r.info?.realmUserId === username,
);
console.log('realm', realm);
console.log('username looked for: ', username);
return realm;
}

@cached
get defaultWritableRealm(): { path: string; info: RealmInfo } | null {
let maybePersonalRealm = `${this.realmServer.url.href}${this.matrixService.userName}/personal/`;
Expand Down
10 changes: 8 additions & 2 deletions packages/host/tests/acceptance/ai-assistant-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,10 @@ module('Acceptance | AI Assistant tests', function (hooks) {
setupBaseRealm(hooks);

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

class Pet extends CardDef {
Expand Down Expand Up @@ -347,7 +350,10 @@ module('Acceptance | AI Assistant tests', function (hooks) {
await click('[data-test-open-ai-assistant]');
assert.dom('[data-test-llm-select-selected]').hasText('claude-3.5-sonnet');

createAndJoinRoom('@testuser:staging', 'room-test-2');
createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test-2',
});

await click('[data-test-past-sessions-button]');
await waitFor("[data-test-enter-room='mock_room_2']");
Expand Down
5 changes: 4 additions & 1 deletion packages/host/tests/acceptance/basic-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ module('Acceptance | basic tests', function (hooks) {
});

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

let loaderService = lookupLoaderService();
Expand Down
10 changes: 8 additions & 2 deletions packages/host/tests/acceptance/code-submode-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,10 @@ module('Acceptance | code submode tests', function (_hooks) {
}

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

let realmServerService = this.owner.lookup(
Expand Down Expand Up @@ -530,7 +533,10 @@ module('Acceptance | code submode tests', function (_hooks) {
});

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

monacoService = this.owner.lookup(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,10 @@ module('Acceptance | code submode | create-file tests', function (hooks) {
contents: files,
}));

matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

lookupNetworkService().mount(
Expand Down
10 changes: 8 additions & 2 deletions packages/host/tests/acceptance/code-submode/editor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,20 @@ module('Acceptance | code submode | editor tests', function (hooks) {
setupLocalIndexing(hooks);
setupServerSentEvents(hooks);
setupOnSave(hooks);
let { setRealmPermissions, createAndJoinRoom } = setupMockMatrix(hooks, {
let mockMatrixUtils = setupMockMatrix(hooks, {
loggedInAs: '@testuser:staging',
activeRealms: [baseRealm.url, testRealmURL],
});

let { setRealmPermissions, createAndJoinRoom } = mockMatrixUtils;

hooks.beforeEach(async function () {
setRealmPermissions({ [testRealmURL]: ['read', 'write'] });

matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

monacoService = this.owner.lookup(
Expand Down Expand Up @@ -265,6 +270,7 @@ module('Acceptance | code submode | editor tests', function (hooks) {
backgroundURL:
'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg',
iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png',
realmUserId: '@test_realm:localhost',
},
'Person/john-with-bad-pet-link.json': {
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ module('Acceptance | code submode | file-tree tests', function (hooks) {
hooks.beforeEach(async function () {
setRealmPermissions({ [testRealmURL]: ['read', 'write'] });

matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

const numStubFiles = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,10 @@ module('Acceptance | code submode | inspector tests', function (hooks) {
[testRealmURL2]: ['read', 'write'],
});

matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

// this seeds the loader used during index which obtains url mappings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ module('Acceptance | code submode | recent files tests', function (hooks) {
});

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

// this seeds the loader used during index which obtains url mappings
Expand Down
13 changes: 11 additions & 2 deletions packages/host/tests/acceptance/code-submode/schema-editor-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
type TestContextWithSave,
} from '../../helpers';
import { setupMockMatrix } from '../../helpers/mock-matrix';
import { MockUtils } from '../../helpers/mock-matrix/_utils';
import { setupApplicationTest } from '../../helpers/setup';
import '@cardstack/runtime-common/helpers/code-equality-assertion';

Expand Down Expand Up @@ -209,6 +210,7 @@ const ambiguousDisplayNamesCardSource = `
let matrixRoomId: string;
module('Acceptance | code submode | schema editor tests', function (hooks) {
let realm: Realm;
let mockMatrixUtils: MockUtils;

async function saveField(
context: TestContextWithSSE,
Expand All @@ -228,13 +230,19 @@ module('Acceptance | code submode | schema editor tests', function (hooks) {
setupLocalIndexing(hooks);
setupOnSave(hooks);
setupServerSentEvents(hooks);
let { createAndJoinRoom } = setupMockMatrix(hooks, {

mockMatrixUtils = setupMockMatrix(hooks, {
loggedInAs: '@testuser:staging',
activeRealms: [baseRealm.url, testRealmURL],
});

let { createAndJoinRoom } = mockMatrixUtils;

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

// this seeds the loader used during index which obtains url mappings
Expand Down Expand Up @@ -323,6 +331,7 @@ module('Acceptance | code submode | schema editor tests', function (hooks) {
backgroundURL:
'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg',
iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png',
realmUserId: '@test_realm:localhost',
},
},
}));
Expand Down
5 changes: 4 additions & 1 deletion packages/host/tests/acceptance/code-submode/spec-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ module('Spec preview', function (hooks) {
});

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

// this seeds the loader used during index which obtains url mappings
Expand Down
5 changes: 4 additions & 1 deletion packages/host/tests/acceptance/commands-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ module('Acceptance | Commands tests', function (hooks) {
setupBaseRealm(hooks);

hooks.beforeEach(async function () {
matrixRoomId = await createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = await createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

class Pet extends CardDef {
Expand Down
20 changes: 15 additions & 5 deletions packages/host/tests/acceptance/interact-submode-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,19 @@ module('Acceptance | interact submode tests', function (hooks) {
setupLocalIndexing(hooks);
setupServerSentEvents(hooks);
setupOnSave(hooks);
let mockMatrixUtils = setupMockMatrix(hooks, {
loggedInAs: '@testuser:staging',
activeRealms: [testRealmURL, testRealm2URL, testRealm3URL],
});

let { setRealmPermissions, setActiveRealms, createAndJoinRoom } =
setupMockMatrix(hooks, {
loggedInAs: '@testuser:staging',
activeRealms: [testRealmURL, testRealm2URL, testRealm3URL],
});
mockMatrixUtils;

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

let loader = lookupLoaderService().loader;
Expand Down Expand Up @@ -1756,6 +1761,7 @@ module('Acceptance | interact submode tests', function (hooks) {
});

test<TestContextWithSSE>('stack item live updates with error', async function (assert) {
console.log('test started?');
assert.expect(7);
let expectedEvents = [
{
Expand All @@ -1774,6 +1780,7 @@ module('Acceptance | interact submode tests', function (hooks) {
},
},
];
console.log('visitOperatorMode');
await visitOperatorMode({
stacks: [
[
Expand All @@ -1784,6 +1791,7 @@ module('Acceptance | interact submode tests', function (hooks) {
],
],
});
console.log('visit cgomplete');
assert
.dom(`[data-test-stack-card="${testRealmURL}Person/fadhlan"]`)
.exists('card is displayed');
Expand All @@ -1793,6 +1801,8 @@ module('Acceptance | interact submode tests', function (hooks) {
)
.doesNotExist('card error state is NOT displayed');

console.log('about to expect events');

await this.expectEvents({
assert,
realm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ module('Acceptance | operator mode tests', function (hooks) {
});

hooks.beforeEach(async function () {
matrixRoomId = createAndJoinRoom('@testuser:staging', 'room-test');
matrixRoomId = createAndJoinRoom({
sender: '@testuser:staging',
name: 'room-test',
});
setupUserSubscription(matrixRoomId);

setExpiresInSec(60 * 60);
Expand Down
Loading
Loading