Skip to content

Commit

Permalink
feat!: add AgentMessageSentEvent and associate records to outbound me…
Browse files Browse the repository at this point in the history
…ssages (openwallet-foundation#1099)

Signed-off-by: Ariel Gentile <gentilester@gmail.com>
  • Loading branch information
genaris authored and Artemkaaas committed Dec 5, 2022
1 parent 6dc5f39 commit 2dd03cc
Show file tree
Hide file tree
Showing 57 changed files with 1,249 additions and 935 deletions.
29 changes: 22 additions & 7 deletions packages/action-menu/src/ActionMenuApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
ConnectionService,
Dispatcher,
MessageSender,
createOutboundDidCommV1Message,
OutboundMessageContext,
injectable,
} from '@aries-framework/core'

Expand Down Expand Up @@ -59,8 +59,13 @@ export class ActionMenuApi {
connection,
})

const outboundMessage = createOutboundDidCommV1Message(connection, message)
await this.messageSender.sendMessage(this.agentContext, outboundMessage)
const outboundMessageContext = new OutboundMessageContext(message, {
agentContext: this.agentContext,
connection,
associatedRecord: record,
})

await this.messageSender.sendMessage(outboundMessageContext)

return record
}
Expand All @@ -80,8 +85,13 @@ export class ActionMenuApi {
menu: options.menu,
})

const outboundMessage = createOutboundDidCommV1Message(connection, message)
await this.messageSender.sendMessage(this.agentContext, outboundMessage)
const outboundMessageContext = new OutboundMessageContext(message, {
agentContext: this.agentContext,
connection,
associatedRecord: record,
})

await this.messageSender.sendMessage(outboundMessageContext)

return record
}
Expand Down Expand Up @@ -109,8 +119,13 @@ export class ActionMenuApi {
performedAction: options.performedAction,
})

const outboundMessage = createOutboundDidCommV1Message(connection, message)
await this.messageSender.sendMessage(this.agentContext, outboundMessage)
const outboundMessageContext = new OutboundMessageContext(message, {
agentContext: this.agentContext,
connection,
associatedRecord: record,
})

await this.messageSender.sendMessage(outboundMessageContext)

return record
}
Expand Down
68 changes: 28 additions & 40 deletions packages/core/src/agent/Dispatcher.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
import type {
ConstructableDidCommMessage,
OutboundDidCommV1Message,
OutboundDidCommV1ServiceMessage,
OutboundDidCommV2Message,
} from '../didcomm'
import type { ParsedMessageType } from '../utils/messageType'
import type { AgentMessage } from './AgentMessage'
import type { AgentMessageProcessedEvent } from './Events'
import type { Handler } from './Handler'
import type { InboundMessageContext } from './models/InboundMessageContext'

import { InjectionSymbols } from '../constants'
import { AriesFrameworkError } from '../error/AriesFrameworkError'
import { Logger } from '../logger'
import { inject, injectable } from '../plugins'
import { injectable, inject } from '../plugins'
import { canHandleMessageType, parseMessageType } from '../utils/messageType'

import { ProblemReportMessage } from './../modules/problem-reports/messages/ProblemReportMessage'
import { EventEmitter } from './EventEmitter'
import { AgentEventTypes } from './Events'
import { MessageSender } from './MessageSender'
import { isOutboundDidCommV1Message, isOutboundDidCommV2Message, isOutboundServiceMessage } from './helpers'
import { OutboundMessageContext } from './models'

@injectable()
class Dispatcher {
Expand All @@ -43,14 +37,14 @@ class Dispatcher {
}

public async dispatch(messageContext: InboundMessageContext): Promise<void> {
const message = messageContext.message
const { agentContext, connection, senderKey, recipientKey, message } = messageContext
const handler = this.getHandlerForType(message.type)

if (!handler) {
throw new AriesFrameworkError(`No handler for message type "${message.type}" found`)
}

let outboundMessage: OutboundDidCommV1Message | OutboundDidCommV1ServiceMessage | OutboundDidCommV2Message | void
let outboundMessage: OutboundMessageContext<AgentMessage> | void

try {
outboundMessage = await handler.handle(messageContext)
Expand All @@ -59,45 +53,39 @@ class Dispatcher {

if (problemReportMessage instanceof ProblemReportMessage && messageContext.connection) {
problemReportMessage.setThread({
threadId: messageContext.message.threadId,
threadId: message.threadId,
})
outboundMessage = {
payload: problemReportMessage,
outboundMessage = new OutboundMessageContext(problemReportMessage, {
agentContext,
connection: messageContext.connection,
}
})
} else {
this.logger.error(`Error handling message with type ${message.type}`, {
message: message.toJSON(),
error,
senderKey: messageContext.senderKey?.fingerprint,
recipientKey: messageContext.recipientKey?.fingerprint,
connectionId: messageContext.connection?.id,
senderKey: senderKey?.fingerprint,
recipientKey: recipientKey?.fingerprint,
connectionId: connection?.id,
})

throw error
}
}

if (outboundMessage && isOutboundServiceMessage(outboundMessage)) {
await this.messageSender.sendMessageToService(messageContext.agentContext, {
message: outboundMessage.payload,
service: outboundMessage.service,
senderKey: outboundMessage.senderKey,
returnRoute: true,
})
} else if (outboundMessage && isOutboundDidCommV1Message(outboundMessage)) {
outboundMessage.sessionId = messageContext.sessionId
await this.messageSender.sendMessage(messageContext.agentContext, outboundMessage)
} else if (outboundMessage && isOutboundDidCommV2Message(outboundMessage)) {
await this.messageSender.sendMessage(messageContext.agentContext, outboundMessage)
if (outboundMessage) {
if (outboundMessage.isOutboundServiceMessage()) {
await this.messageSender.sendMessageToService(outboundMessage)
} else {
outboundMessage.sessionId = messageContext.sessionId
await this.messageSender.sendMessage(outboundMessage)
}
}

// Emit event that allows to hook into received messages
this.eventEmitter.emit<AgentMessageProcessedEvent>(messageContext.agentContext, {
this.eventEmitter.emit<AgentMessageProcessedEvent>(agentContext, {
type: AgentEventTypes.AgentMessageProcessed,
payload: {
message: messageContext.message,
connection: messageContext.connection,
message,
connection,
},
})
}
Expand All @@ -112,8 +100,9 @@ class Dispatcher {
}
}

public getMessageClassForType(messageType: string): ConstructableDidCommMessage | undefined {
public getMessageClassForType(messageType: string): typeof AgentMessage | undefined {
const incomingMessageType = parseMessageType(messageType)

for (const handler of this.handlers) {
for (const MessageClass of handler.supportedMessages) {
if (canHandleMessageType(MessageClass, incomingMessageType)) return MessageClass
Expand All @@ -125,11 +114,10 @@ class Dispatcher {
* Returns array of message types that dispatcher is able to handle.
* Message type format is MTURI specified at https://github.com/hyperledger/aries-rfcs/blob/main/concepts/0003-protocols/README.md#mturi.
*/
public get supportedMessageTypes(): ParsedMessageType[] {
return this.handlers.reduce<ParsedMessageType[]>(
(all, cur) => [...all, ...cur.supportedMessages.map((message) => message.type)],
[]
)
public get supportedMessageTypes() {
return this.handlers
.reduce<typeof AgentMessage[]>((all, cur) => [...all, ...cur.supportedMessages], [])
.map((m) => m.type)
}

/**
Expand Down
10 changes: 10 additions & 0 deletions packages/core/src/agent/Events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ConnectionRecord } from '../modules/connections'
import type { AgentMessage } from './AgentMessage'
import type { OutboundMessageContext, OutboundMessageSendStatus } from './models'
import type { Observable } from 'rxjs'

import { filter } from 'rxjs'
Expand All @@ -13,6 +14,7 @@ export function filterContextCorrelationId(contextCorrelationId: string) {
export enum AgentEventTypes {
AgentMessageReceived = 'AgentMessageReceived',
AgentMessageProcessed = 'AgentMessageProcessed',
AgentMessageSent = 'AgentMessageSent',
}

export interface EventMetadata {
Expand Down Expand Up @@ -41,3 +43,11 @@ export interface AgentMessageProcessedEvent extends BaseEvent {
connection?: ConnectionRecord
}
}

export interface AgentMessageSentEvent extends BaseEvent {
type: typeof AgentEventTypes.AgentMessageSent
payload: {
message: OutboundMessageContext
status: OutboundMessageSendStatus
}
}
17 changes: 5 additions & 12 deletions packages/core/src/agent/Handler.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import type {
ConstructableDidCommMessage,
OutboundDidCommV1Message,
OutboundDidCommV1ServiceMessage,
OutboundDidCommV2Message,
} from '../didcomm'
import type { InboundMessageContext } from './models/InboundMessageContext'
import type { ConstructableAgentMessage } from './AgentMessage'
import type { InboundMessageContext, OutboundMessageContext } from './models'

export interface Handler {
readonly supportedMessages: readonly ConstructableDidCommMessage[]
readonly supportedMessages: readonly ConstructableAgentMessage[]

handle(
messageContext: InboundMessageContext
): Promise<OutboundDidCommV1Message | OutboundDidCommV1ServiceMessage | OutboundDidCommV2Message | void>
handle(messageContext: InboundMessageContext): Promise<OutboundMessageContext | void>
}

/**
* Provides exact typing for the DIDCommMessage in the message context in the `handle` function
* Provides exact typing for the AgentMessage in the message context in the `handle` function
* of a handler. It takes all possible types from `supportedMessageTypes`
*
* @example
Expand Down
Loading

0 comments on commit 2dd03cc

Please sign in to comment.