Skip to content

Commit 545404c

Browse files
committed
SOFIE-318 | allow returning error from adlib actions in blueprints (WIP)
1 parent a22a0a0 commit 545404c

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

meteor/server/api/rest/v1/playlists.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class PlaylistsServerAPI implements PlaylistsRestAPI {
201201
)
202202
)
203203

204-
return ServerClientAPI.runUserActionInLogForPlaylistOnWorker(
204+
const result = await ServerClientAPI.runUserActionInLogForPlaylistOnWorker(
205205
this.context.getMethodContext(connection),
206206
event,
207207
getCurrentTime(),
@@ -220,6 +220,19 @@ class PlaylistsServerAPI implements PlaylistsRestAPI {
220220
actionOptions: adLibOptions,
221221
}
222222
)
223+
if (ClientAPI.isClientResponseError(result)) return result
224+
// Check if the action rejected the request
225+
if (result.result?.errorMessage) {
226+
return ClientAPI.responseError(
227+
UserError.from(
228+
new Error(result.result.errorMessage),
229+
UserErrorMessage.InternalError,
230+
undefined,
231+
400
232+
)
233+
)
234+
}
235+
return ClientAPI.responseSuccess(result.result ?? {})
223236
} else {
224237
return ClientAPI.responseError(
225238
UserError.from(new Error(`No adLib with Id ${adLibId}`), UserErrorMessage.AdlibNotFound, undefined, 412)
@@ -268,7 +281,7 @@ class PlaylistsServerAPI implements PlaylistsRestAPI {
268281
)
269282
}
270283

271-
return ServerClientAPI.runUserActionInLogForPlaylistOnWorker(
284+
const result = await ServerClientAPI.runUserActionInLogForPlaylistOnWorker(
272285
this.context.getMethodContext(connection),
273286
event,
274287
getCurrentTime(),
@@ -286,6 +299,14 @@ class PlaylistsServerAPI implements PlaylistsRestAPI {
286299
triggerMode: triggerMode ?? undefined,
287300
}
288301
)
302+
if (ClientAPI.isClientResponseError(result)) return result
303+
// Check if the action rejected the request
304+
if (result.result?.errorMessage) {
305+
return ClientAPI.responseError(
306+
UserError.from(new Error(result.result.errorMessage), UserErrorMessage.InternalError, undefined, 400)
307+
)
308+
}
309+
return ClientAPI.responseSuccess(result.result ?? {})
289310
}
290311
async moveNextPart(
291312
connection: Meteor.Connection,
@@ -602,6 +623,7 @@ export function registerRoutes(registerRoute: APIRegisterHook<PlaylistsRestAPI>)
602623
'post',
603624
'/playlists/:playlistId/execute-adlib',
604625
new Map([
626+
[400, []],
605627
[404, [UserErrorMessage.RundownPlaylistNotFound]],
606628
[412, [UserErrorMessage.InactiveRundown, UserErrorMessage.NoCurrentPart, UserErrorMessage.AdlibNotFound]],
607629
]),
@@ -638,6 +660,7 @@ export function registerRoutes(registerRoute: APIRegisterHook<PlaylistsRestAPI>)
638660
'post',
639661
'/playlists/:playlistId/execute-bucket-adlib',
640662
new Map([
663+
[400, []],
641664
[404, [UserErrorMessage.RundownPlaylistNotFound]],
642665
[
643666
412,

packages/blueprints-integration/src/context/adlibActionContext.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ export interface IActionExecutionContext
4343
/** Insert a queued part to follow the taken part */
4444
queuePartAfterTake(part: IBlueprintPart, pieces: IBlueprintPiece[]): void
4545

46+
/**
47+
* Reject the action request with an error message.
48+
* This will cause the API to return a 400 error response.
49+
* @param message Error message to return to the client
50+
*/
51+
rejectRequest(message: string): void
52+
4653
/** Misc actions */
4754
// updateAction(newManifest: Pick<IBlueprintAdLibActionManifest, 'description' | 'payload'>): void // only updates itself. to allow for the next one to do something different
4855
// executePeripheralDeviceAction(deviceId: string, functionName: string, args: any[]): Promise<any>

packages/corelib/src/worker/studio.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ export interface ExecuteBucketAdLibOrActionProps extends RundownPlayoutPropsBase
285285
export interface ExecuteActionResult {
286286
queuedPartInstanceId?: PartInstanceId
287287
taken?: boolean
288+
/** If set, the action was rejected - contains the error message */
289+
errorMessage?: string
288290
}
289291
export interface TakeNextPartProps extends RundownPlayoutPropsBase {
290292
fromPartInstanceId: PartInstanceId | null

packages/job-worker/src/blueprints/context/adlibActions.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct
8282

8383
public partToQueueAfterTake: QueueablePartAndPieces | undefined
8484

85+
/**
86+
* If set, the blueprint has rejected the request with an error message
87+
*/
88+
public requestError: string | undefined
89+
8590
public get quickLoopInfo(): BlueprintQuickLookInfo | null {
8691
return this.partAndPieceInstanceService.quickLoopInfo
8792
}
@@ -280,4 +285,8 @@ export class ActionExecutionContext extends ShowStyleUserContext implements IAct
280285
getCurrentTime(): number {
281286
return getCurrentTime()
282287
}
288+
289+
rejectRequest(message: string): void {
290+
this.requestError = message
291+
}
283292
}

packages/job-worker/src/playout/__tests__/playout-executeAction.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,28 @@ describe('Playout API', () => {
200200

201201
expect(takeNextPartMock).toHaveBeenCalledTimes(0)
202202
})
203+
204+
test('rejectRequest returns error message', async () => {
205+
const errorMessage = 'This action is not allowed right now'
206+
207+
context.updateShowStyleBlueprint({
208+
executeAction: async (context) => {
209+
context.rejectRequest(errorMessage)
210+
},
211+
})
212+
213+
const actionDocId: AdLibActionId = protectString('action-id')
214+
const actionId = 'some-action'
215+
const userData = { blobby: true }
216+
const result = await handleExecuteAdlibAction(context, {
217+
playlistId,
218+
actionDocId,
219+
actionId,
220+
userData,
221+
})
222+
223+
expect(result.errorMessage).toBe(errorMessage)
224+
expect(result.taken).toBeFalsy()
225+
})
203226
})
204227
})

packages/job-worker/src/playout/adlibAction.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ export async function executeActionInner(
276276
return {
277277
queuedPartInstanceId: actionContext.queuedPartInstanceId,
278278
taken: actionContext.takeAfterExecute,
279+
errorMessage: actionContext.requestError,
279280
}
280281
}
281282

0 commit comments

Comments
 (0)