From 49a62c452427f76133f08655f93a7420f216eb9d Mon Sep 17 00:00:00 2001 From: Rob Moffat Date: Tue, 24 Sep 2024 16:30:01 +0100 Subject: [PATCH] Working on heartbeats --- .../demo/src/client/da/dummy-desktop-agent.ts | 10 ++--- .../fdc3-web-impl/src/BasicFDC3Server.ts | 10 ++--- .../fdc3-web-impl/src/ServerContext.ts | 8 ++-- .../src/handlers/BroadcastHandler.ts | 32 +++++++-------- .../src/handlers/HeartbeatHandler.ts | 21 +++++----- .../src/handlers/IntentHandler.ts | 40 +++++++++---------- .../fdc3-web-impl/src/handlers/OpenHandler.ts | 22 +++++----- .../fdc3-web-impl/src/handlers/support.ts | 10 ++--- .../test/support/TestServerContext.ts | 2 +- 9 files changed, 79 insertions(+), 76 deletions(-) diff --git a/toolbox/fdc3-for-web/demo/src/client/da/dummy-desktop-agent.ts b/toolbox/fdc3-for-web/demo/src/client/da/dummy-desktop-agent.ts index aad840fb2..2fcc1da65 100644 --- a/toolbox/fdc3-for-web/demo/src/client/da/dummy-desktop-agent.ts +++ b/toolbox/fdc3-for-web/demo/src/client/da/dummy-desktop-agent.ts @@ -3,14 +3,14 @@ import { v4 as uuid } from 'uuid' import { APP_GOODBYE, APP_HELLO, DA_HELLO, FDC3_APP_EVENT } from "../../message-types"; import { DemoServerContext } from "./DemoServerContext"; import { FDC3_2_1_JSONDirectory } from "./FDC3_2_1_JSONDirectory"; -import { DefaultFDC3Server, DirectoryApp, ServerContext } from "@kite9/fdc3-web-impl"; +import { AppRegistration, DefaultFDC3Server, DirectoryApp, ServerContext } from "@kite9/fdc3-web-impl"; import { ChannelState, ChannelType } from "@kite9/fdc3-web-impl/src/handlers/BroadcastHandler"; import { link } from "./util"; import { BrowserTypes } from "@kite9/fdc3-schema"; type WebConnectionProtocol2LoadURL = BrowserTypes.WebConnectionProtocol2LoadURL -function createAppStartButton(app: DirectoryApp, sc: ServerContext): HTMLDivElement { +function createAppStartButton(app: DirectoryApp, sc: ServerContext): HTMLDivElement { const div = document.createElement("div") as HTMLDivElement div.classList.add("app") const h3 = document.createElement("h3") @@ -55,8 +55,8 @@ window.addEventListener("load", () => { socket.emit(DA_HELLO, desktopAgentUUID) const directory = new FDC3_2_1_JSONDirectory() - //await directory.load("/static/da/appd.json") - await directory.load("/static/da/local-conformance-2_0.v2.json") + await directory.load("/static/da/appd.json") + //await directory.load("/static/da/local-conformance-2_0.v2.json") //await directory.load("/static/da/training-appd.v2.json") const sc = new DemoServerContext(socket, directory) @@ -65,7 +65,7 @@ window.addEventListener("load", () => { { id: "two", type: ChannelType.user, context: [], displayMetadata: { name: "THE BLUE CHANNEL", color: "blue" } }, { id: "three", type: ChannelType.user, context: [], displayMetadata: { name: "THE GREEN CHANNEL", color: "green" } } ] - const fdc3Server = new DefaultFDC3Server(sc, directory, channelDetails, false, 20000, 10000) + const fdc3Server = new DefaultFDC3Server(sc, directory, channelDetails, true, 20000, 10000) socket.on(FDC3_APP_EVENT, (msg, from) => { console.log(`App Event ${JSON.stringify(msg, null, 2)} from ${from}`) diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts index 4c1107a6c..50b76092a 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/BasicFDC3Server.ts @@ -1,5 +1,5 @@ import { FDC3Server } from "./FDC3Server"; -import { InstanceID, ServerContext } from "./ServerContext"; +import { AppRegistration, InstanceID, ServerContext } from "./ServerContext"; import { BroadcastHandler, ChannelState } from "./handlers/BroadcastHandler"; import { IntentHandler } from "./handlers/IntentHandler"; import { Directory } from "./directory/DirectoryInterface"; @@ -15,7 +15,7 @@ export interface MessageHandler { /** * Handles an AgentRequestMessage from the messaging source */ - accept(msg: any, sc: ServerContext, from: InstanceID): void + accept(msg: any, sc: ServerContext, from: InstanceID): void shutdown(): void } @@ -26,9 +26,9 @@ export interface MessageHandler { export class BasicFDC3Server implements FDC3Server { private handlers: MessageHandler[] - private sc: ServerContext + private sc: ServerContext - constructor(handlers: MessageHandler[], sc: ServerContext) { + constructor(handlers: MessageHandler[], sc: ServerContext) { this.handlers = handlers this.sc = sc; } @@ -45,7 +45,7 @@ export class BasicFDC3Server implements FDC3Server { export class DefaultFDC3Server extends BasicFDC3Server { - constructor(sc: ServerContext, directory: Directory, userChannels: ChannelState[], heartbeats: boolean, intentTimeoutMs: number = 20000, openHandlerTimeoutMs: number = 3000) { + constructor(sc: ServerContext, directory: Directory, userChannels: ChannelState[], heartbeats: boolean, intentTimeoutMs: number = 20000, openHandlerTimeoutMs: number = 3000) { const handlers: MessageHandler[] = [ new BroadcastHandler(userChannels), new IntentHandler(directory, intentTimeoutMs), diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts index c8d495c5f..f07216e4a 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/ServerContext.ts @@ -1,4 +1,4 @@ -import { AppIntent, AppIdentifier } from "@kite9/fdc3-standard"; +import { AppIntent } from "@kite9/fdc3-standard"; import { Context } from "@kite9/fdc3-context"; export enum State { @@ -8,8 +8,10 @@ export enum State { Terminated /* App has sent a termination message */ } -export type AppRegistration = AppIdentifier & { - state: State +export type AppRegistration = { + state: State, + appId: string; + instanceId: InstanceID } /** diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts index b74774099..dba34f5f8 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/BroadcastHandler.ts @@ -1,5 +1,5 @@ import { MessageHandler } from "../BasicFDC3Server"; -import { InstanceID, ServerContext } from "../ServerContext"; +import { AppRegistration, InstanceID, ServerContext } from "../ServerContext"; import { Context } from "@kite9/fdc3-context"; import { AppIdentifier, ChannelError, DisplayMetadata } from "@kite9/fdc3-standard"; import { successResponse, errorResponse, onlyUnique } from "./support"; @@ -102,7 +102,7 @@ export class BroadcastHandler implements MessageHandler { } } - accept(msg: any, sc: ServerContext, uuid: InstanceID) { + accept(msg: any, sc: ServerContext, uuid: InstanceID) { const from = sc.getInstanceDetails(uuid) if (from == null) { @@ -146,7 +146,7 @@ export class BroadcastHandler implements MessageHandler { } } - handleCreatePrivateChannelRequest(arg0: CreatePrivateChannelRequest, sc: ServerContext, from: AppIdentifier) { + handleCreatePrivateChannelRequest(arg0: CreatePrivateChannelRequest, sc: ServerContext, from: AppIdentifier) { const id = sc.createUUID() this.state.push({ id, @@ -159,7 +159,7 @@ export class BroadcastHandler implements MessageHandler { successResponse(sc, arg0, from, { privateChannel: { id, type: this.convertChannelTypeToString(ChannelType.private) } }, 'createPrivateChannelResponse') } - handleGetCurrentContextRequest(arg0: GetCurrentContextRequest, sc: ServerContext, from: AppIdentifier) { + handleGetCurrentContextRequest(arg0: GetCurrentContextRequest, sc: ServerContext, from: AppIdentifier) { const channel = this.getChannelById(arg0.payload.channelId) const type = arg0.payload.contextType @@ -171,7 +171,7 @@ export class BroadcastHandler implements MessageHandler { } } - handlePrivateChannelUnsubscribeEventListenerRequest(arg0: PrivateChannelUnsubscribeEventListenerRequest, sc: ServerContext, from: AppIdentifier) { + handlePrivateChannelUnsubscribeEventListenerRequest(arg0: PrivateChannelUnsubscribeEventListenerRequest, sc: ServerContext, from: AppIdentifier) { const i = this.eventListeners.findIndex(r => r.listenerUuid == arg0.payload.listenerUUID) if (i > -1) { this.eventListeners.splice(i, 1) @@ -181,7 +181,7 @@ export class BroadcastHandler implements MessageHandler { } } - handlePrivateChannelDisconnectRequest(arg0: PrivateChannelDisconnectRequest, sc: ServerContext, from: AppIdentifier) { + handlePrivateChannelDisconnectRequest(arg0: PrivateChannelDisconnectRequest, sc: ServerContext, from: AppIdentifier) { const toUnsubscribe = this.contextListeners .filter(r => (r.appId == from.appId) && (r.instanceId == from.instanceId)) .filter(r => r.channelId == arg0.payload.channelId) @@ -195,7 +195,7 @@ export class BroadcastHandler implements MessageHandler { successResponse(sc, arg0, from, {}, 'privateChannelDisconnectResponse') } - handleContextListenerUnsubscribeRequest(arg0: ContextListenerUnsubscribeRequest, sc: ServerContext, from: AppIdentifier) { + handleContextListenerUnsubscribeRequest(arg0: ContextListenerUnsubscribeRequest, sc: ServerContext, from: AppIdentifier) { const i = this.contextListeners .findIndex(r => (r.listenerUuid == arg0.payload.listenerUUID) && (r.instanceId == from.instanceId)) @@ -210,7 +210,7 @@ export class BroadcastHandler implements MessageHandler { } } - handleAddContextListenerRequest(arg0: AddContextListenerRequest, sc: ServerContext, from: AppIdentifier) { + handleAddContextListenerRequest(arg0: AddContextListenerRequest, sc: ServerContext, from: AppIdentifier) { var channelId = null var channelType = ChannelType.user @@ -241,7 +241,7 @@ export class BroadcastHandler implements MessageHandler { } - handleBroadcastRequest(arg0: BroadcastRequest, sc: ServerContext, from: AppIdentifier) { + handleBroadcastRequest(arg0: BroadcastRequest, sc: ServerContext, from: AppIdentifier) { const matchingListeners = this.contextListeners .filter(r => r.channelId == arg0.payload.channelId) .filter(r => r.contextType == null || r.contextType == arg0.payload.context.type) @@ -268,7 +268,7 @@ export class BroadcastHandler implements MessageHandler { successResponse(sc, arg0, from, {}, 'broadcastResponse') } - handleGetCurrentChannelRequest(arg0: GetCurrentChannelRequest, sc: ServerContext, from: AppIdentifier) { + handleGetCurrentChannelRequest(arg0: GetCurrentChannelRequest, sc: ServerContext, from: AppIdentifier) { const currentChannel = this.getCurrentChannel(from) if (currentChannel) { successResponse(sc, arg0, from, { @@ -283,7 +283,7 @@ export class BroadcastHandler implements MessageHandler { } } - handleJoinUserChannelRequest(arg0: JoinUserChannelRequest, sc: ServerContext, from: AppIdentifier) { + handleJoinUserChannelRequest(arg0: JoinUserChannelRequest, sc: ServerContext, from: AppIdentifier) { // check it's a user channel const newChannel = this.getChannelById(arg0.payload.channelId) if ((newChannel == null) || (newChannel.type != ChannelType.user)) { @@ -297,7 +297,7 @@ export class BroadcastHandler implements MessageHandler { successResponse(sc, arg0, from, {}, 'joinUserChannelResponse') } - handleLeaveCurrentChannelRequest(arg0: LeaveCurrentChannelRequest, sc: ServerContext, from: AppIdentifier) { + handleLeaveCurrentChannelRequest(arg0: LeaveCurrentChannelRequest, sc: ServerContext, from: AppIdentifier) { const instanceId = from.instanceId ?? 'no-instance-id' const currentChannel = this.currentChannel[instanceId] if (currentChannel) { @@ -307,7 +307,7 @@ export class BroadcastHandler implements MessageHandler { successResponse(sc, arg0, from, {}, 'leaveCurrentChannelResponse') } - handleGetOrCreateRequest(arg0: GetOrCreateChannelRequest, sc: ServerContext, from: AppIdentifier) { + handleGetOrCreateRequest(arg0: GetOrCreateChannelRequest, sc: ServerContext, from: AppIdentifier) { const id = arg0.payload.channelId var channel = this.getChannelById(id) if (channel) { @@ -328,12 +328,12 @@ export class BroadcastHandler implements MessageHandler { } - handleGetUserChannelsRequest(arg0: GetUserChannelsRequest, sc: ServerContext, from: AppIdentifier) { + handleGetUserChannelsRequest(arg0: GetUserChannelsRequest, sc: ServerContext, from: AppIdentifier) { const userChannels = this.state.filter(c => c.type == ChannelType.user) successResponse(sc, arg0, from, { userChannels: userChannels.map(c => ({ id: c.id, type: this.convertChannelTypeToString(c.type), displayMetadata: c.displayMetadata })) }, 'getUserChannelsResponse') } - handlePrivateChannelAddEventListenerRequest(arg0: PrivateChannelAddEventListenerRequest, from: AppIdentifier, sc: ServerContext) { + handlePrivateChannelAddEventListenerRequest(arg0: PrivateChannelAddEventListenerRequest, from: AppIdentifier, sc: ServerContext) { const channel = this.getChannelById(arg0.payload.privateChannelId) if ((channel == null) || (channel.type != ChannelType.private)) { @@ -351,7 +351,7 @@ export class BroadcastHandler implements MessageHandler { } } - invokeEventListeners(privateChannelId: string | null, eventType: PrivateChannelEventListenerTypes, messageType: NotificationAgentEventMessage, sc: ServerContext, contextType?: string) { + invokeEventListeners(privateChannelId: string | null, eventType: PrivateChannelEventListenerTypes, messageType: NotificationAgentEventMessage, sc: ServerContext, contextType?: string) { if (privateChannelId) { const msg = { type: messageType, diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts index 28d6be08f..1bd98cb30 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/HeartbeatHandler.ts @@ -10,17 +10,15 @@ export class HeartbeatHandler implements MessageHandler { private readonly contexts: ServerContext[] = [] private readonly lastHeartbeats: Map = new Map() - private readonly warnings: Set = new Set() private readonly timerFunction: NodeJS.Timeout - constructor(pingInterval: number = 1000, warnAfter: number = 5000, deadAfter: number = 10000) { + constructor(pingInterval: number = 1000, disconnectedAfter: number = 5000, deadAfter: number = 10000) { this.timerFunction = setInterval(() => { + console.log(`Contexts: ${this.contexts.length} Last Heartbeats: `, this.heartbeatTimes()) + this.contexts.forEach(async (sc) => { const allAops = await sc.getAllApps() - - console.log(`Last Heartbeats: `, this.heartbeatTimes()) - allAops .filter(app => (app.state == State.Connected) || (app.state == State.NotResponding)) .forEach(app => { @@ -33,14 +31,14 @@ export class HeartbeatHandler implements MessageHandler { if (lastHeartbeat != undefined) { const timeSinceLastHeartbeat = now - lastHeartbeat - if (timeSinceLastHeartbeat < warnAfter) { - this.warnings.delete(app.instanceId!!) - } else if ((timeSinceLastHeartbeat > warnAfter) && (!this.warnings.has(app.instanceId!!))) { - console.warn(`No heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms`) - this.warnings.add(app.instanceId!!) - } else if (timeSinceLastHeartbeat > deadAfter) { + if (timeSinceLastHeartbeat < disconnectedAfter) { + sc.setAppState(app.instanceId!!, State.Connected) + } else if ((timeSinceLastHeartbeat > disconnectedAfter) && (!this.warnings.has(app.instanceId!!))) { console.error(`No heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms. App is considered not responding.`) sc.setAppState(app.instanceId!!, State.NotResponding) + } else if (timeSinceLastHeartbeat > deadAfter) { + console.error(`No heartbeat from ${app.instanceId} for ${timeSinceLastHeartbeat}ms. App is considered terminated.`) + sc.setAppState(app.instanceId!!, State.Terminated) } else { // no action } @@ -81,6 +79,7 @@ export class HeartbeatHandler implements MessageHandler { const app = sc.getInstanceDetails(from) if (app) { sc.setAppState(from, State.Terminated) + this } } } diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts index f60265708..d43d4c8df 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/IntentHandler.ts @@ -1,5 +1,5 @@ import { MessageHandler } from "../BasicFDC3Server"; -import { InstanceID, ServerContext } from "../ServerContext"; +import { AppRegistration, InstanceID, ServerContext } from "../ServerContext"; import { Directory, DirectoryIntent } from "../directory/DirectoryInterface"; import { Context } from "@kite9/fdc3-context"; import { AppIntent, ResolveError, AppIdentifier, } from "@kite9/fdc3-standard"; @@ -34,7 +34,7 @@ type IntentRequest = { /** * Re-writes the request to forward it on to the target application */ -async function forwardRequest(arg0: IntentRequest, to: AppIdentifier, sc: ServerContext, ih: IntentHandler): Promise { +async function forwardRequest(arg0: IntentRequest, to: AppIdentifier, sc: ServerContext, ih: IntentHandler): Promise { const out: IntentEvent = { type: 'intentEvent', payload: { @@ -74,10 +74,10 @@ class PendingIntent { complete: boolean = false r: IntentRequest appId: AppIdentifier - sc: ServerContext + sc: ServerContext ih: IntentHandler - constructor(r: IntentRequest, sc: ServerContext, ih: IntentHandler, appId: AppIdentifier) { + constructor(r: IntentRequest, sc: ServerContext, ih: IntentHandler, appId: AppIdentifier) { this.r = r this.appId = appId this.sc = sc @@ -120,12 +120,12 @@ export class IntentHandler implements MessageHandler { shutdown(): void { } - async narrowIntents(appIntents: AppIntent[], context: Context, sc: ServerContext): Promise { + async narrowIntents(appIntents: AppIntent[], context: Context, sc: ServerContext): Promise { const out = await sc.narrowIntents(appIntents, context) return out } - async accept(msg: any, sc: ServerContext, uuid: InstanceID): Promise { + async accept(msg: any, sc: ServerContext, uuid: InstanceID): Promise { const from = sc.getInstanceDetails(uuid) if (from == null) { @@ -160,7 +160,7 @@ export class IntentHandler implements MessageHandler { /** * Called when target app handles an intent */ - intentResultRequest(arg0: IntentResultRequest, sc: ServerContext, from: AppIdentifier): void | PromiseLike { + intentResultRequest(arg0: IntentResultRequest, sc: ServerContext, from: AppIdentifier): void | PromiseLike { const requestId = arg0.payload.raiseIntentRequestUuid const to = this.pendingResolutions.get(requestId) if (to) { @@ -178,7 +178,7 @@ export class IntentHandler implements MessageHandler { } } - onUnsubscribe(arg0: IntentListenerUnsubscribeRequest, sc: ServerContext, from: AppIdentifier): void { + onUnsubscribe(arg0: IntentListenerUnsubscribeRequest, sc: ServerContext, from: AppIdentifier): void { const id = arg0.payload.listenerUUID const fi = this.regs.findIndex((e) => e.listenerUUID == id) if (fi > -1) { @@ -189,7 +189,7 @@ export class IntentHandler implements MessageHandler { } } - onAddIntentListener(arg0: AddIntentListenerRequest, sc: ServerContext, from: AppIdentifier): void { + onAddIntentListener(arg0: AddIntentListenerRequest, sc: ServerContext, from: AppIdentifier): void { const lr = { appId: from.appId, instanceId: from.instanceId, @@ -215,11 +215,11 @@ export class IntentHandler implements MessageHandler { return this.regs.find(r => (r.instanceId == instanceId) && (r.intentName == intentName)) != null } - async getRunningApps(appId: string, sc: ServerContext): Promise { + async getRunningApps(appId: string, sc: ServerContext): Promise { return (await sc.getConnectedApps()).filter(a => a.appId == appId) } - async startWithPendingIntent(arg0: IntentRequest, sc: ServerContext, target: AppIdentifier): Promise { + async startWithPendingIntent(arg0: IntentRequest, sc: ServerContext, target: AppIdentifier): Promise { // app exists but needs starting const pi = new PendingIntent(arg0, sc, this, target) this.pendingIntents.add(pi) @@ -238,7 +238,7 @@ export class IntentHandler implements MessageHandler { }) } - async raiseIntentRequestToSpecificInstance(arg0: IntentRequest[], sc: ServerContext, target: AppIdentifier): Promise { + async raiseIntentRequestToSpecificInstance(arg0: IntentRequest[], sc: ServerContext, target: AppIdentifier): Promise { if (!(await sc.isAppConnected(target.instanceId!!))) { // instance doesn't exist return errorResponseId(sc, arg0[0].requestUuid, arg0[0].from, ResolveError.TargetInstanceUnavailable, arg0[0].type) @@ -254,7 +254,7 @@ export class IntentHandler implements MessageHandler { } } - async createPendingIntentIfAllowed(ir: IntentRequest, sc: ServerContext, target: AppIdentifier) { + async createPendingIntentIfAllowed(ir: IntentRequest, sc: ServerContext, target: AppIdentifier) { // if this app declares that it supports the intent, we'll create a pending intent const matchingIntents: DirectoryIntent[] = this.directory.retrieveIntents(ir.context.type, ir.intent, undefined) const declared = matchingIntents.find(i => i.appId == target.appId) @@ -268,7 +268,7 @@ export class IntentHandler implements MessageHandler { } } - async raiseIntentRequestToSpecificAppId(arg0: IntentRequest[], sc: ServerContext, target: AppIdentifier): Promise { + async raiseIntentRequestToSpecificAppId(arg0: IntentRequest[], sc: ServerContext, target: AppIdentifier): Promise { // dealing with a specific app, which may or may not be open const runningApps = await this.getRunningApps(target.appId, sc) @@ -316,7 +316,7 @@ export class IntentHandler implements MessageHandler { return (uniqueApps == 1) } - async raiseIntentToAnyApp(arg0: IntentRequest[], sc: ServerContext): Promise { + async raiseIntentToAnyApp(arg0: IntentRequest[], sc: ServerContext): Promise { const connectedApps = await sc.getConnectedApps() const matchingIntents = arg0.flatMap(i => this.directory.retrieveIntents(i.context.type, i.intent, undefined)) const uniqueIntentNames = matchingIntents.map(i => i.intentName).filter((v, i, a) => a.indexOf(v) === i) @@ -373,7 +373,7 @@ export class IntentHandler implements MessageHandler { } - async raiseIntentRequest(arg0: RaiseIntentRequest, sc: ServerContext, from: AppIdentifier): Promise { + async raiseIntentRequest(arg0: RaiseIntentRequest, sc: ServerContext, from: AppIdentifier): Promise { const intentRequest: IntentRequest = { context: arg0.payload.context, from, @@ -392,7 +392,7 @@ export class IntentHandler implements MessageHandler { } } - async raiseIntentForContextRequest(arg0: RaiseIntentForContextRequest, sc: ServerContext, from: AppIdentifier): Promise { + async raiseIntentForContextRequest(arg0: RaiseIntentForContextRequest, sc: ServerContext, from: AppIdentifier): Promise { // dealing with a specific instance of an app const mappedIntents = this.directory.retrieveIntents(arg0.payload.context.type, undefined, undefined) const uniqueIntentNames = mappedIntents.filter((v, i, a) => a.findIndex(v2 => v2.intentName == v.intentName) == i) @@ -420,7 +420,7 @@ export class IntentHandler implements MessageHandler { } } - async findIntentsByContextRequest(r: FindIntentsByContextRequest, sc: ServerContext, from: AppIdentifier): Promise { + async findIntentsByContextRequest(r: FindIntentsByContextRequest, sc: ServerContext, from: AppIdentifier): Promise { // TODO: Add result type const { context } = r.payload @@ -454,7 +454,7 @@ export class IntentHandler implements MessageHandler { } - async findIntentRequest(r: FindIntentRequest, sc: ServerContext, from: AppIdentifier): Promise { + async findIntentRequest(r: FindIntentRequest, sc: ServerContext, from: AppIdentifier): Promise { const { intent, context, resultType } = r.payload // listeners for connected applications @@ -494,7 +494,7 @@ export class IntentHandler implements MessageHandler { }, 'findIntentResponse') } - async retrieveListeners(intentName: string | undefined, sc: ServerContext): Promise { + async retrieveListeners(intentName: string | undefined, sc: ServerContext): Promise { const activeApps = await sc.getConnectedApps() const matching = this.regs.filter(r => r.intentName == intentName) diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts index f2b82ae92..81c7c7b11 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/OpenHandler.ts @@ -1,5 +1,5 @@ import { MessageHandler } from "../BasicFDC3Server"; -import { InstanceID, ServerContext, State } from "../ServerContext"; +import { AppRegistration, InstanceID, ServerContext, State } from "../ServerContext"; import { Directory, DirectoryApp } from "../directory/DirectoryInterface"; import { ContextElement } from "@kite9/fdc3-context"; import { @@ -23,14 +23,14 @@ enum AppState { Opening, DeliveringContext, Done } class PendingApp { - private readonly sc: ServerContext + private readonly sc: ServerContext private readonly msg: OpenRequest readonly context: ContextElement | undefined readonly source: AppMetadata state: AppState = AppState.Opening private openedApp: AppIdentifier | undefined = undefined - constructor(sc: ServerContext, msg: OpenRequest, context: ContextElement | undefined, source: AppIdentifier, timeoutMs: number) { + constructor(sc: ServerContext, msg: OpenRequest, context: ContextElement | undefined, source: AppIdentifier, timeoutMs: number) { this.context = context this.source = source this.sc = sc @@ -86,7 +86,7 @@ export class OpenHandler implements MessageHandler { shutdown(): void { } - async accept(msg: any, sc: ServerContext, uuid: InstanceID): Promise { + async accept(msg: any, sc: ServerContext, uuid: InstanceID): Promise { switch (msg.type as string) { case 'addContextListenerRequest': return this.handleAddContextListener(msg as AddContextListenerRequest, sc, uuid) case 'WCP4ValidateAppIdentity': return this.handleValidate(msg as WebConnectionProtocol4ValidateAppIdentity, sc, uuid) @@ -103,7 +103,7 @@ export class OpenHandler implements MessageHandler { } } catch (e: any) { const responseType = msg.type.replace(new RegExp("Request$"), 'Response') - errorResponse(sc, msg, from, e.message ?? e, responseType) + errorResponse(sc, msg, from!!, e.message ?? e, responseType) } } @@ -111,7 +111,7 @@ export class OpenHandler implements MessageHandler { /** * This deals with sending pending context to listeners of newly-opened apps. */ - handleAddContextListener(arg0: AddContextListenerRequest, sc: ServerContext, from: InstanceID): void { + handleAddContextListener(arg0: AddContextListenerRequest, sc: ServerContext, from: InstanceID): void { const pendingOpen = this.pending.get(from) if (pendingOpen) { @@ -160,7 +160,7 @@ export class OpenHandler implements MessageHandler { } } - getAppMetadata(arg0: GetAppMetadataRequest, sc: ServerContext, from: AppIdentifier): void { + getAppMetadata(arg0: GetAppMetadataRequest, sc: ServerContext, from: AppIdentifier): void { const appID = arg0.payload.app const details = this.directory.retrieveAppsById(appID.appId) if (details.length > 0) { @@ -173,7 +173,7 @@ export class OpenHandler implements MessageHandler { } - async findInstances(arg0: FindInstancesRequest, sc: ServerContext, from: AppIdentifier): Promise { + async findInstances(arg0: FindInstancesRequest, sc: ServerContext, from: AppIdentifier): Promise { const appId = arg0.payload.app.appId const openApps = await sc.getConnectedApps() const matching = openApps.filter(a => a.appId == appId).map(a => { @@ -187,7 +187,7 @@ export class OpenHandler implements MessageHandler { }, 'findInstancesResponse') } - async open(arg0: OpenRequest, sc: ServerContext, from: AppIdentifier): Promise { + async open(arg0: OpenRequest, sc: ServerContext, from: AppIdentifier): Promise { const source = arg0.payload.app const context = arg0.payload.context @@ -200,7 +200,7 @@ export class OpenHandler implements MessageHandler { } } - async handleValidate(arg0: WebConnectionProtocol4ValidateAppIdentity, sc: ServerContext, from: InstanceID): Promise { + async handleValidate(arg0: WebConnectionProtocol4ValidateAppIdentity, sc: ServerContext, from: InstanceID): Promise { const _this = this const responseMeta = { @@ -250,6 +250,7 @@ export class OpenHandler implements MessageHandler { // in this case, the app is reconnecting, so let's just re-assign the // identity sc.setInstanceDetails(from, appIdentity) + sc.setAppState(from, State.Connected) return returnSuccess(appIdentity) } } @@ -257,6 +258,7 @@ export class OpenHandler implements MessageHandler { // we need to assign an identity to this app const appIdentity = sc.getInstanceDetails(from) if (appIdentity) { + sc.setAppState(appIdentity.instanceId, State.Connected) returnSuccess(appIdentity) // make sure if the opener is listening for this app to open gets informed diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts index ef56c27f7..f8fe3889c 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/src/handlers/support.ts @@ -1,19 +1,19 @@ -import { ServerContext } from "../ServerContext"; +import { AppRegistration, ServerContext } from "../ServerContext"; import { BrowserTypes } from "@kite9/fdc3-schema"; import { AppIdentifier } from "@kite9/fdc3-standard"; type AppRequestMessage = BrowserTypes.AppRequestMessage type AgentResponseMessage = BrowserTypes.AgentResponseMessage -export function successResponse(sc: ServerContext, request: AppRequestMessage, to: AppIdentifier, payload: any, type: string) { +export function successResponse(sc: ServerContext, request: AppRequestMessage, to: AppIdentifier, payload: any, type: string) { return successResponseId(sc, request.meta.requestUuid, to, payload, type); } -export function errorResponse(sc: ServerContext, request: AppRequestMessage, to: AppIdentifier, error: string, type: string) { +export function errorResponse(sc: ServerContext, request: AppRequestMessage, to: AppIdentifier, error: string, type: string) { return errorResponseId(sc, request.meta.requestUuid, to, error, type); } -export function successResponseId(sc: ServerContext, requestId: string, to: AppIdentifier, payload: any, type: string) { +export function successResponseId(sc: ServerContext, requestId: string, to: AppIdentifier, payload: any, type: string) { sc.post({ meta: { responseUuid: sc.createUUID(), @@ -25,7 +25,7 @@ export function successResponseId(sc: ServerContext, requestId: string, to: } as AgentResponseMessage, to.instanceId!!) } -export function errorResponseId(sc: ServerContext, requestId: string, to: AppIdentifier, error: string, type: string) { +export function errorResponseId(sc: ServerContext, requestId: string, to: AppIdentifier, error: string, type: string) { sc.post({ meta: { responseUuid: sc.createUUID(), diff --git a/toolbox/fdc3-for-web/fdc3-web-impl/test/support/TestServerContext.ts b/toolbox/fdc3-for-web/fdc3-web-impl/test/support/TestServerContext.ts index 91abf717a..5ce3a2cb3 100644 --- a/toolbox/fdc3-for-web/fdc3-web-impl/test/support/TestServerContext.ts +++ b/toolbox/fdc3-for-web/fdc3-web-impl/test/support/TestServerContext.ts @@ -121,7 +121,7 @@ export class TestServerContext implements ServerContext { getInstanceUUID(appId: AppIdentifier): InstanceID { this.setInstanceDetails(appId.instanceId!!, { appId: appId.appId, - instanceId: appId.instanceId, + instanceId: appId.instanceId!!, state: State.Connected }) return appId.instanceId!!