@contember/engine-actions 2.1.0-alpha.2 → 2.1.0-alpha.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/dist/development/index.cjs +10 -5
  2. package/dist/development/index.cjs.map +1 -1
  3. package/dist/development/index.js +10 -5
  4. package/dist/development/index.js.map +1 -1
  5. package/dist/development/src/authorization/ActionsAuthorizationActions.cjs +2 -0
  6. package/dist/development/src/authorization/ActionsAuthorizationActions.cjs.map +1 -1
  7. package/dist/development/src/authorization/ActionsAuthorizationActions.js +2 -0
  8. package/dist/development/src/authorization/ActionsAuthorizationActions.js.map +1 -1
  9. package/dist/development/src/dispatch/EventsRepository.cjs +17 -4
  10. package/dist/development/src/dispatch/EventsRepository.cjs.map +1 -1
  11. package/dist/development/src/dispatch/EventsRepository.js +17 -4
  12. package/dist/development/src/dispatch/EventsRepository.js.map +1 -1
  13. package/dist/development/src/dispatch/ProjectDispatcher.cjs +2 -2
  14. package/dist/development/src/dispatch/ProjectDispatcher.cjs.map +1 -1
  15. package/dist/development/src/dispatch/ProjectDispatcher.js +1 -1
  16. package/dist/development/src/dispatch/ProjectDispatcher.js.map +1 -1
  17. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.cjs +1 -0
  18. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.cjs.map +1 -1
  19. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.js +1 -0
  20. package/dist/development/src/graphql/http/ActionsApiMiddlewareFactory.js.map +1 -1
  21. package/dist/development/src/graphql/resolvers/ResolversFactory.cjs +7 -2
  22. package/dist/development/src/graphql/resolvers/ResolversFactory.cjs.map +1 -1
  23. package/dist/development/src/graphql/resolvers/ResolversFactory.js +7 -2
  24. package/dist/development/src/graphql/resolvers/ResolversFactory.js.map +1 -1
  25. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs +21 -0
  26. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs.map +1 -0
  27. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.js +21 -0
  28. package/dist/development/src/graphql/resolvers/mutation/RetryEventMutationResolver.js.map +1 -0
  29. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs +19 -0
  30. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs.map +1 -0
  31. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.js +19 -0
  32. package/dist/development/src/graphql/resolvers/mutation/StopEventMutationResolver.js.map +1 -0
  33. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.cjs +10 -0
  34. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.cjs.map +1 -1
  35. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.js +10 -0
  36. package/dist/development/src/graphql/resolvers/query/EventsQueryResolver.js.map +1 -1
  37. package/dist/development/src/graphql/schema/actions.graphql.cjs +11 -0
  38. package/dist/development/src/graphql/schema/actions.graphql.cjs.map +1 -1
  39. package/dist/development/src/graphql/schema/actions.graphql.js +11 -0
  40. package/dist/development/src/graphql/schema/actions.graphql.js.map +1 -1
  41. package/dist/development/src/model/EventByIdQuery.cjs +17 -0
  42. package/dist/development/src/model/EventByIdQuery.cjs.map +1 -0
  43. package/dist/development/src/model/EventByIdQuery.js +17 -0
  44. package/dist/development/src/model/EventByIdQuery.js.map +1 -0
  45. package/dist/development/src/triggers/TriggerPayloadPersister.cjs +2 -3
  46. package/dist/development/src/triggers/TriggerPayloadPersister.cjs.map +1 -1
  47. package/dist/development/src/triggers/TriggerPayloadPersister.js +2 -3
  48. package/dist/development/src/triggers/TriggerPayloadPersister.js.map +1 -1
  49. package/dist/development/src/utils/notifyChannel.cjs +9 -0
  50. package/dist/development/src/utils/notifyChannel.cjs.map +1 -0
  51. package/dist/development/src/utils/notifyChannel.js +9 -0
  52. package/dist/development/src/utils/notifyChannel.js.map +1 -0
  53. package/dist/production/index.cjs +10 -5
  54. package/dist/production/index.cjs.map +1 -1
  55. package/dist/production/index.js +10 -5
  56. package/dist/production/index.js.map +1 -1
  57. package/dist/production/src/authorization/ActionsAuthorizationActions.cjs +2 -0
  58. package/dist/production/src/authorization/ActionsAuthorizationActions.cjs.map +1 -1
  59. package/dist/production/src/authorization/ActionsAuthorizationActions.js +2 -0
  60. package/dist/production/src/authorization/ActionsAuthorizationActions.js.map +1 -1
  61. package/dist/production/src/dispatch/EventsRepository.cjs +17 -4
  62. package/dist/production/src/dispatch/EventsRepository.cjs.map +1 -1
  63. package/dist/production/src/dispatch/EventsRepository.js +17 -4
  64. package/dist/production/src/dispatch/EventsRepository.js.map +1 -1
  65. package/dist/production/src/dispatch/ProjectDispatcher.cjs +2 -2
  66. package/dist/production/src/dispatch/ProjectDispatcher.cjs.map +1 -1
  67. package/dist/production/src/dispatch/ProjectDispatcher.js +1 -1
  68. package/dist/production/src/dispatch/ProjectDispatcher.js.map +1 -1
  69. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.cjs +1 -0
  70. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.cjs.map +1 -1
  71. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.js +1 -0
  72. package/dist/production/src/graphql/http/ActionsApiMiddlewareFactory.js.map +1 -1
  73. package/dist/production/src/graphql/resolvers/ResolversFactory.cjs +7 -2
  74. package/dist/production/src/graphql/resolvers/ResolversFactory.cjs.map +1 -1
  75. package/dist/production/src/graphql/resolvers/ResolversFactory.js +7 -2
  76. package/dist/production/src/graphql/resolvers/ResolversFactory.js.map +1 -1
  77. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs +21 -0
  78. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.cjs.map +1 -0
  79. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.js +21 -0
  80. package/dist/production/src/graphql/resolvers/mutation/RetryEventMutationResolver.js.map +1 -0
  81. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs +19 -0
  82. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.cjs.map +1 -0
  83. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.js +19 -0
  84. package/dist/production/src/graphql/resolvers/mutation/StopEventMutationResolver.js.map +1 -0
  85. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.cjs +10 -0
  86. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.cjs.map +1 -1
  87. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.js +10 -0
  88. package/dist/production/src/graphql/resolvers/query/EventsQueryResolver.js.map +1 -1
  89. package/dist/production/src/graphql/schema/actions.graphql.cjs +11 -0
  90. package/dist/production/src/graphql/schema/actions.graphql.cjs.map +1 -1
  91. package/dist/production/src/graphql/schema/actions.graphql.js +11 -0
  92. package/dist/production/src/graphql/schema/actions.graphql.js.map +1 -1
  93. package/dist/production/src/model/EventByIdQuery.cjs +17 -0
  94. package/dist/production/src/model/EventByIdQuery.cjs.map +1 -0
  95. package/dist/production/src/model/EventByIdQuery.js +17 -0
  96. package/dist/production/src/model/EventByIdQuery.js.map +1 -0
  97. package/dist/production/src/triggers/TriggerPayloadPersister.cjs +2 -3
  98. package/dist/production/src/triggers/TriggerPayloadPersister.cjs.map +1 -1
  99. package/dist/production/src/triggers/TriggerPayloadPersister.js +2 -3
  100. package/dist/production/src/triggers/TriggerPayloadPersister.js.map +1 -1
  101. package/dist/production/src/utils/notifyChannel.cjs +9 -0
  102. package/dist/production/src/utils/notifyChannel.cjs.map +1 -0
  103. package/dist/production/src/utils/notifyChannel.js +9 -0
  104. package/dist/production/src/utils/notifyChannel.js.map +1 -0
  105. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  106. package/dist/types/authorization/ActionsAuthorizationActions.d.ts +10 -0
  107. package/dist/types/authorization/ActionsAuthorizationActions.d.ts.map +1 -1
  108. package/dist/types/dispatch/EventsRepository.d.ts +2 -1
  109. package/dist/types/dispatch/EventsRepository.d.ts.map +1 -1
  110. package/dist/types/graphql/http/ActionsApiMiddlewareFactory.d.ts.map +1 -1
  111. package/dist/types/graphql/resolvers/ActionsContext.d.ts +3 -0
  112. package/dist/types/graphql/resolvers/ActionsContext.d.ts.map +1 -1
  113. package/dist/types/graphql/resolvers/ResolversFactory.d.ts +4 -2
  114. package/dist/types/graphql/resolvers/ResolversFactory.d.ts.map +1 -1
  115. package/dist/types/graphql/resolvers/mutation/RetryEventMutationResolver.d.ts +11 -0
  116. package/dist/types/graphql/resolvers/mutation/RetryEventMutationResolver.d.ts.map +1 -0
  117. package/dist/types/graphql/resolvers/mutation/StopEventMutationResolver.d.ts +11 -0
  118. package/dist/types/graphql/resolvers/mutation/StopEventMutationResolver.d.ts.map +1 -0
  119. package/dist/types/graphql/resolvers/mutation/index.d.ts +2 -0
  120. package/dist/types/graphql/resolvers/mutation/index.d.ts.map +1 -1
  121. package/dist/types/graphql/resolvers/query/EventsQueryResolver.d.ts +3 -0
  122. package/dist/types/graphql/resolvers/query/EventsQueryResolver.d.ts.map +1 -1
  123. package/dist/types/graphql/schema/actions.graphql.d.ts.map +1 -1
  124. package/dist/types/graphql/schema/index.d.ts +39 -2
  125. package/dist/types/graphql/schema/index.d.ts.map +1 -1
  126. package/dist/types/index.d.ts.map +1 -1
  127. package/dist/types/model/EventByIdQuery.d.ts +8 -0
  128. package/dist/types/model/EventByIdQuery.d.ts.map +1 -0
  129. package/dist/types/triggers/TriggerPayloadPersister.d.ts +0 -1
  130. package/dist/types/triggers/TriggerPayloadPersister.d.ts.map +1 -1
  131. package/dist/types/tsconfig.tsbuildinfo +1 -1
  132. package/dist/types/utils/notifyChannel.d.ts +4 -0
  133. package/dist/types/utils/notifyChannel.d.ts.map +1 -0
  134. package/graphql.codegen.yml +2 -2
  135. package/package.json +15 -15
  136. package/src/authorization/ActionsAuthorizationActions.ts +2 -0
  137. package/src/dispatch/EventsRepository.ts +24 -5
  138. package/src/dispatch/ProjectDispatcher.ts +1 -1
  139. package/src/graphql/http/ActionsApiMiddlewareFactory.ts +1 -0
  140. package/src/graphql/resolvers/ActionsContext.ts +1 -0
  141. package/src/graphql/resolvers/ResolversFactory.ts +6 -1
  142. package/src/graphql/resolvers/mutation/RetryEventMutationResolver.ts +22 -0
  143. package/src/graphql/resolvers/mutation/StopEventMutationResolver.ts +19 -0
  144. package/src/graphql/resolvers/mutation/index.ts +2 -0
  145. package/src/graphql/resolvers/query/EventsQueryResolver.ts +11 -0
  146. package/src/graphql/schema/actions.graphql.ts +11 -0
  147. package/src/graphql/schema/index.ts +48 -1
  148. package/src/index.ts +9 -5
  149. package/src/model/EventByIdQuery.ts +21 -0
  150. package/src/triggers/TriggerPayloadPersister.ts +3 -2
  151. package/src/utils/notifyChannel.ts +6 -0
@@ -0,0 +1,4 @@
1
+ import { Client } from '@contember/database';
2
+ export declare const NOTIFY_CHANNEL_NAME = "actions_event";
3
+ export declare const notify: (db: Client, projectSlug: string) => Promise<void>;
4
+ //# sourceMappingURL=notifyChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifyChannel.d.ts","sourceRoot":"","sources":["../../../src/utils/notifyChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,eAAO,MAAM,mBAAmB,kBAAkB,CAAA;AAClD,eAAO,MAAM,MAAM,GAAU,IAAI,MAAM,EAAE,aAAa,MAAM,kBAE3D,CAAA"}
@@ -10,7 +10,7 @@ generates:
10
10
  enumsAsTypes: "1"
11
11
  scalars:
12
12
  DateTime: Date
13
- Uuid: String
13
+ Uuid: string
14
14
  Json: any
15
15
  plugins:
16
16
  - "typescript"
@@ -18,4 +18,4 @@ generates:
18
18
  - "typescript-resolvers"
19
19
  hooks:
20
20
  afterAllFileWrite:
21
- - yarn run -T eslint --fix
21
+ - bun run eslint --fix
package/package.json CHANGED
@@ -22,20 +22,20 @@
22
22
  }
23
23
  },
24
24
  "dependencies": {
25
- "@contember/authorization": "2.1.0-alpha.2",
26
- "@contember/database": "2.1.0-alpha.2",
27
- "@contember/database-migrations": "2.1.0-alpha.2",
28
- "@contember/engine-common": "2.1.0-alpha.2",
29
- "@contember/engine-content-api": "2.1.0-alpha.2",
30
- "@contember/engine-http": "2.1.0-alpha.2",
31
- "@contember/engine-plugins": "2.1.0-alpha.2",
32
- "@contember/engine-system-api": "2.1.0-alpha.2",
33
- "@contember/engine-tenant-api": "2.1.0-alpha.2",
34
- "@contember/graphql-utils": "2.1.0-alpha.2",
35
- "@contember/logger": "2.1.0-alpha.2",
36
- "@contember/schema": "2.1.0-alpha.2",
37
- "@contember/schema-utils": "2.1.0-alpha.2",
38
- "@contember/typesafe": "2.1.0-alpha.2",
25
+ "@contember/authorization": "2.1.0-alpha.21",
26
+ "@contember/database": "2.1.0-alpha.21",
27
+ "@contember/database-migrations": "2.1.0-alpha.21",
28
+ "@contember/engine-common": "2.1.0-alpha.21",
29
+ "@contember/engine-content-api": "2.1.0-alpha.21",
30
+ "@contember/engine-http": "2.1.0-alpha.21",
31
+ "@contember/engine-plugins": "2.1.0-alpha.21",
32
+ "@contember/engine-system-api": "2.1.0-alpha.21",
33
+ "@contember/engine-tenant-api": "2.1.0-alpha.21",
34
+ "@contember/graphql-utils": "2.1.0-alpha.21",
35
+ "@contember/logger": "2.1.0-alpha.21",
36
+ "@contember/schema": "2.1.0-alpha.21",
37
+ "@contember/schema-utils": "2.1.0-alpha.21",
38
+ "@contember/typesafe": "2.1.0-alpha.21",
39
39
  "@graphql-tools/schema": "^10.0.7",
40
40
  "graphql-tag": "^2.12.6"
41
41
  },
@@ -49,5 +49,5 @@
49
49
  "pg": "^8.5.0"
50
50
  },
51
51
  "type": "module",
52
- "version": "2.1.0-alpha.2"
52
+ "version": "2.1.0-alpha.21"
53
53
  }
@@ -11,4 +11,6 @@ export namespace ActionsAuthorizationActions {
11
11
 
12
12
  export const EVENTS_VIEW = Authorizator.createAction(Resources.events, 'view')
13
13
  export const EVENTS_PROCESS = Authorizator.createAction(Resources.events, 'process')
14
+ export const EVENTS_RETRY = Authorizator.createAction(Resources.events, 'retry')
15
+ export const EVENTS_STOP = Authorizator.createAction(Resources.events, 'stop')
14
16
  }
@@ -11,6 +11,7 @@ import {
11
11
  import { EventRow, HandledEvent } from './types'
12
12
  import { Actions } from '@contember/schema'
13
13
  import { eventsToProcessSpecification, eventsToProcessStateSpecification } from '../model/EventsToProcessSpecification'
14
+ import { notify } from '../utils/notifyChannel'
14
15
 
15
16
 
16
17
  const ACK_TIMEOUT_MS = 1_000 * 60 * 10 // 10 minutes
@@ -87,15 +88,33 @@ export class EventsRepository {
87
88
  })
88
89
  }
89
90
 
90
- public async requeue(db: Client, events: EventRow[]): Promise<void> {
91
+ public async requeue(db: Client, events: string[]): Promise<void> {
91
92
  await UpdateBuilder.create()
92
93
  .table('actions_event')
93
94
  .values<EventRow>({
94
- state: it => it.raw('CASE WHEN num_retries = 0 THEN ? ELSE ? END', 'created', 'retrying'),
95
+ state: it => it.raw(`
96
+ CASE
97
+ WHEN num_retries = 0 THEN
98
+ ?::__SCHEMA__.actions_trigger_state
99
+ ELSE
100
+ ?::__SCHEMA__.actions_trigger_state END
101
+ `, 'created', 'retrying'),
95
102
  last_state_change: new Date(),
96
103
  visible_at: new Date(),
97
104
  })
98
- .where(it => it.in('id', events.map(it => it.id)))
105
+ .where(it => it.in('id', events))
106
+ .execute(db)
107
+ }
108
+
109
+ public async markStopped(db: Client, events: string[]): Promise<void> {
110
+ await UpdateBuilder.create()
111
+ .table('actions_event')
112
+ .values<EventRow>({
113
+ state: 'stopped',
114
+ last_state_change: new Date(),
115
+ resolved_at: new Date(),
116
+ })
117
+ .where(it => it.in('id', events))
99
118
  .execute(db)
100
119
  }
101
120
 
@@ -114,7 +133,7 @@ export class EventsRepository {
114
133
  }
115
134
 
116
135
  private async markFailed(db: Client, event: HandledEvent): Promise<void> {
117
- const numRetries = event.row.num_retries
136
+ const numRetries = event.row.num_retries + 1
118
137
  const now = new Date()
119
138
  const nextAttempt = new Date()
120
139
  nextAttempt.setTime(nextAttempt.getTime() + (event.target?.initialRepeatIntervalMs ?? DEFAULT_REPEAT_INTERVAL_MS) * Math.pow(2, event.row.num_retries))
@@ -122,7 +141,7 @@ export class EventsRepository {
122
141
  .table('actions_event')
123
142
  .values<EventRow>({
124
143
  last_state_change: now,
125
- num_retries: event.row.num_retries + 1,
144
+ num_retries: numRetries,
126
145
  log: JSON.stringify([...event.row.log, event.result]) as any,
127
146
  ...(numRetries < (event.target?.maxAttempts ?? DEFAULT_MAX_ATTEMPTS) ? {
128
147
  state: 'retrying',
@@ -3,7 +3,7 @@ import { EventDispatcher } from './EventDispatcher'
3
3
  import { ContentSchemaResolver } from '@contember/engine-http'
4
4
  import { Runnable, RunnableArgs, Running } from '@contember/engine-common'
5
5
  import { Listener } from '@contember/database'
6
- import { NOTIFY_CHANNEL_NAME } from '../triggers/TriggerPayloadPersister'
6
+ import { NOTIFY_CHANNEL_NAME } from '../utils/notifyChannel'
7
7
 
8
8
 
9
9
  export class ProjectDispatcherFactory {
@@ -25,6 +25,7 @@ export class ActionsApiMiddlewareFactory {
25
25
  const graphqlContext: ActionsContext = {
26
26
  db: systemDatabase,
27
27
  logger,
28
+ project: projectContainer.project,
28
29
  contentSchemaResolver: projectContainer.contentSchemaResolver,
29
30
  requireAccess: async (action, message) => {
30
31
  if (!(await this.authorizator.isAllowed(identity, new AuthorizationScope.Global(), action))) {
@@ -7,5 +7,6 @@ export interface ActionsContext {
7
7
  logger: Logger
8
8
  db: DatabaseContext
9
9
  contentSchemaResolver: ContentSchemaResolver
10
+ project: { slug: string }
10
11
  requireAccess: (action: Authorizator.Action, message?: string) => Promise<void>
11
12
  }
@@ -1,7 +1,7 @@
1
1
  import { DateTimeType, JSONType, UuidType } from '@contember/graphql-utils'
2
2
  import { Resolvers } from '../schema'
3
3
  import { EventsQueryResolver } from './query'
4
- import { ProcessBatchMutationResolver, SetVariablesMutationResolver } from './mutation'
4
+ import { ProcessBatchMutationResolver, RetryEventMutationResolver, SetVariablesMutationResolver, StopEventMutationResolver } from './mutation'
5
5
  import { ActionsContext } from './ActionsContext'
6
6
  import { VariablesQueryResolver } from './query/VariablesQueryResolver'
7
7
 
@@ -11,6 +11,8 @@ export class ResolversFactory {
11
11
  private readonly processBatchMutationResolver: ProcessBatchMutationResolver,
12
12
  private readonly variablesQueryResolver: VariablesQueryResolver,
13
13
  private readonly setVariablesMutationResolver: SetVariablesMutationResolver,
14
+ private readonly retryEventMutationResolver: RetryEventMutationResolver,
15
+ private readonly stopEventMutationResolver: StopEventMutationResolver,
14
16
  ) {
15
17
  }
16
18
 
@@ -22,11 +24,14 @@ export class ResolversFactory {
22
24
  Mutation: {
23
25
  processBatch: this.processBatchMutationResolver.processBatch.bind(this.processBatchMutationResolver),
24
26
  setVariables: this.setVariablesMutationResolver.setVariables.bind(this.setVariablesMutationResolver),
27
+ retryEvent: this.retryEventMutationResolver.retryEvent.bind(this.retryEventMutationResolver),
28
+ stopEvent: this.stopEventMutationResolver.stopEvent.bind(this.stopEventMutationResolver),
25
29
  },
26
30
  Query: {
27
31
  eventsInProcessing: this.eventsQueryResolver.eventsInProcessing.bind(this.eventsQueryResolver),
28
32
  eventsToProcess: this.eventsQueryResolver.eventsToProcess.bind(this.eventsQueryResolver),
29
33
  failedEvents: this.eventsQueryResolver.failedEvents.bind(this.eventsQueryResolver),
34
+ event: this.eventsQueryResolver.event.bind(this.eventsQueryResolver),
30
35
  variables: this.variablesQueryResolver.variables.bind(this.variablesQueryResolver),
31
36
  },
32
37
  }
@@ -0,0 +1,22 @@
1
+ import { MutationResolvers, MutationRetryEventArgs } from '../../schema'
2
+ import { ActionsContext } from '../ActionsContext'
3
+ import { ActionsAuthorizationActions } from '../../../authorization'
4
+ import { EventsRepository } from '../../../dispatch/EventsRepository'
5
+ import { notify } from '../../../utils/notifyChannel'
6
+
7
+ export class RetryEventMutationResolver implements MutationResolvers<ActionsContext> {
8
+ constructor(
9
+ private readonly eventsRepository: EventsRepository,
10
+ ) {
11
+ }
12
+ async retryEvent(parent: unknown, args: MutationRetryEventArgs, ctx: ActionsContext) {
13
+ await ctx.requireAccess(ActionsAuthorizationActions.EVENTS_RETRY)
14
+
15
+ await this.eventsRepository.requeue(ctx.db.client, [args.id])
16
+ await notify(ctx.db.client, ctx.project.slug)
17
+
18
+ return {
19
+ ok: true,
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,19 @@
1
+ import { MutationResolvers, MutationRetryEventArgs } from '../../schema'
2
+ import { ActionsContext } from '../ActionsContext'
3
+ import { ActionsAuthorizationActions } from '../../../authorization'
4
+ import { EventsRepository } from '../../../dispatch/EventsRepository'
5
+
6
+ export class StopEventMutationResolver implements MutationResolvers<ActionsContext> {
7
+ constructor(
8
+ private readonly eventsRepository: EventsRepository,
9
+ ) {
10
+ }
11
+ async stopEvent(parent: unknown, args: MutationRetryEventArgs, ctx: ActionsContext) {
12
+ await ctx.requireAccess(ActionsAuthorizationActions.EVENTS_STOP)
13
+
14
+ await this.eventsRepository.markStopped(ctx.db.client, [args.id])
15
+ return {
16
+ ok: true,
17
+ }
18
+ }
19
+ }
@@ -1,2 +1,4 @@
1
1
  export * from './ProcessBatchMutationResolver'
2
2
  export * from './SetVariablesMutationResolver'
3
+ export * from './RetryEventMutationResolver'
4
+ export * from './StopEventMutationResolver'
@@ -13,6 +13,7 @@ import { Client, DatabaseQuery } from '@contember/database'
13
13
  import { EventsInProcessingQuery } from '../../../model/EventsInProcessingQuery'
14
14
  import { FailedEventsQuery } from '../../../model/FailedEventsQuery'
15
15
  import { ActionsAuthorizationActions } from '../../../authorization'
16
+ import { EventByIdQuery } from '../../../model/EventByIdQuery'
16
17
 
17
18
  export class EventsQueryResolver implements QueryResolvers<ActionsContext> {
18
19
  async eventsInProcessing(parent: unknown, { args }: QueryEventsInProcessingArgs, ctx: ActionsContext) {
@@ -33,6 +34,16 @@ export class EventsQueryResolver implements QueryResolvers<ActionsContext> {
33
34
  return await this.fetchEvents(ctx.db, new FailedEventsQuery(args ?? {}))
34
35
  }
35
36
 
37
+ async event(parent: unknown, { id }: { id: string }, ctx: ActionsContext): Promise<Event | null> {
38
+ await ctx.requireAccess(ActionsAuthorizationActions.EVENTS_VIEW)
39
+ const stages = await this.fetchStagesMap(ctx.db)
40
+ const result = await ctx.db.queryHandler.fetch(new EventByIdQuery(id))
41
+ if (!result) {
42
+ return null
43
+ }
44
+ return this.mapEventRows([result], stages)[0]
45
+ }
46
+
36
47
  private async fetchEvents(db: DatabaseContext, query: DatabaseQuery<EventRow[]>) {
37
48
  const stages = await this.fetchStagesMap(db)
38
49
  return this.mapEventRows(await db.queryHandler.fetch(query), stages)
@@ -15,11 +15,14 @@ export const schema: DocumentNode = gql`
15
15
  failedEvents(args: EventArgs): [Event!]!
16
16
  eventsToProcess(args: EventArgs): [Event!]!
17
17
  eventsInProcessing(args: EventArgs): [Event!]!
18
+ event(id: Uuid!): Event
18
19
  variables: [Variable!]!
19
20
  }
20
21
 
21
22
  type Mutation {
22
23
  processBatch: ProcessBatchResponse!
24
+ retryEvent(id: Uuid!): RetryEventResponse!
25
+ stopEvent(id: Uuid!): StopEventResponse!
23
26
  setVariables(args: SetVariablesArgs!): SetVariablesResponse!
24
27
  }
25
28
 
@@ -56,6 +59,14 @@ export const schema: DocumentNode = gql`
56
59
  type ProcessBatchResponse {
57
60
  ok: Boolean!
58
61
  }
62
+
63
+ type RetryEventResponse {
64
+ ok: Boolean!
65
+ }
66
+
67
+ type StopEventResponse {
68
+ ok: Boolean!
69
+ }
59
70
 
60
71
  input SetVariablesArgs {
61
72
  variables: [VariableInput!]!
@@ -16,7 +16,7 @@ export type Scalars = {
16
16
  Float: { input: number; output: number }
17
17
  DateTime: { input: Date; output: Date }
18
18
  Json: { input: any; output: any }
19
- Uuid: { input: String; output: String }
19
+ Uuid: { input: string; output: string }
20
20
  }
21
21
 
22
22
  export type Event = {
@@ -52,7 +52,14 @@ export type EventState =
52
52
  export type Mutation = {
53
53
  readonly __typename?: 'Mutation'
54
54
  readonly processBatch: ProcessBatchResponse
55
+ readonly retryEvent: RetryEventResponse
55
56
  readonly setVariables: SetVariablesResponse
57
+ readonly stopEvent: StopEventResponse
58
+ }
59
+
60
+
61
+ export type MutationRetryEventArgs = {
62
+ id: Scalars['Uuid']['input']
56
63
  }
57
64
 
58
65
 
@@ -60,6 +67,11 @@ export type MutationSetVariablesArgs = {
60
67
  args: SetVariablesArgs
61
68
  }
62
69
 
70
+
71
+ export type MutationStopEventArgs = {
72
+ id: Scalars['Uuid']['input']
73
+ }
74
+
63
75
  export type ProcessBatchResponse = {
64
76
  readonly __typename?: 'ProcessBatchResponse'
65
77
  readonly ok: Scalars['Boolean']['output']
@@ -67,6 +79,7 @@ export type ProcessBatchResponse = {
67
79
 
68
80
  export type Query = {
69
81
  readonly __typename?: 'Query'
82
+ readonly event?: Maybe<Event>
70
83
  readonly eventsInProcessing: ReadonlyArray<Event>
71
84
  readonly eventsToProcess: ReadonlyArray<Event>
72
85
  readonly failedEvents: ReadonlyArray<Event>
@@ -74,6 +87,11 @@ export type Query = {
74
87
  }
75
88
 
76
89
 
90
+ export type QueryEventArgs = {
91
+ id: Scalars['Uuid']['input']
92
+ }
93
+
94
+
77
95
  export type QueryEventsInProcessingArgs = {
78
96
  args?: InputMaybe<EventArgs>
79
97
  }
@@ -88,6 +106,11 @@ export type QueryFailedEventsArgs = {
88
106
  args?: InputMaybe<EventArgs>
89
107
  }
90
108
 
109
+ export type RetryEventResponse = {
110
+ readonly __typename?: 'RetryEventResponse'
111
+ readonly ok: Scalars['Boolean']['output']
112
+ }
113
+
91
114
  export type SetVariablesArgs = {
92
115
  readonly mode?: InputMaybe<SetVariablesMode>
93
116
  readonly variables: ReadonlyArray<VariableInput>
@@ -109,6 +132,11 @@ export type SetVariablesResponse = {
109
132
  readonly ok: Scalars['Boolean']['output']
110
133
  }
111
134
 
135
+ export type StopEventResponse = {
136
+ readonly __typename?: 'StopEventResponse'
137
+ readonly ok: Scalars['Boolean']['output']
138
+ }
139
+
112
140
  export type Variable = {
113
141
  readonly __typename?: 'Variable'
114
142
  readonly name: Scalars['String']['output']
@@ -201,9 +229,11 @@ export type ResolversTypes = {
201
229
  Mutation: ResolverTypeWrapper<{}>
202
230
  ProcessBatchResponse: ResolverTypeWrapper<ProcessBatchResponse>
203
231
  Query: ResolverTypeWrapper<{}>
232
+ RetryEventResponse: ResolverTypeWrapper<RetryEventResponse>
204
233
  SetVariablesArgs: SetVariablesArgs
205
234
  SetVariablesMode: SetVariablesMode
206
235
  SetVariablesResponse: ResolverTypeWrapper<SetVariablesResponse>
236
+ StopEventResponse: ResolverTypeWrapper<StopEventResponse>
207
237
  String: ResolverTypeWrapper<Scalars['String']['output']>
208
238
  Uuid: ResolverTypeWrapper<Scalars['Uuid']['output']>
209
239
  Variable: ResolverTypeWrapper<Variable>
@@ -221,8 +251,10 @@ export type ResolversParentTypes = {
221
251
  Mutation: {}
222
252
  ProcessBatchResponse: ProcessBatchResponse
223
253
  Query: {}
254
+ RetryEventResponse: RetryEventResponse
224
255
  SetVariablesArgs: SetVariablesArgs
225
256
  SetVariablesResponse: SetVariablesResponse
257
+ StopEventResponse: StopEventResponse
226
258
  String: Scalars['String']['output']
227
259
  Uuid: Scalars['Uuid']['output']
228
260
  Variable: Variable
@@ -255,7 +287,9 @@ export interface JsonScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes
255
287
 
256
288
  export type MutationResolvers<ContextType = any, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = {
257
289
  processBatch?: Resolver<ResolversTypes['ProcessBatchResponse'], ParentType, ContextType>
290
+ retryEvent?: Resolver<ResolversTypes['RetryEventResponse'], ParentType, ContextType, RequireFields<MutationRetryEventArgs, 'id'>>
258
291
  setVariables?: Resolver<ResolversTypes['SetVariablesResponse'], ParentType, ContextType, RequireFields<MutationSetVariablesArgs, 'args'>>
292
+ stopEvent?: Resolver<ResolversTypes['StopEventResponse'], ParentType, ContextType, RequireFields<MutationStopEventArgs, 'id'>>
259
293
  }
260
294
 
261
295
  export type ProcessBatchResponseResolvers<ContextType = any, ParentType extends ResolversParentTypes['ProcessBatchResponse'] = ResolversParentTypes['ProcessBatchResponse']> = {
@@ -264,17 +298,28 @@ export type ProcessBatchResponseResolvers<ContextType = any, ParentType extends
264
298
  }
265
299
 
266
300
  export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
301
+ event?: Resolver<Maybe<ResolversTypes['Event']>, ParentType, ContextType, RequireFields<QueryEventArgs, 'id'>>
267
302
  eventsInProcessing?: Resolver<ReadonlyArray<ResolversTypes['Event']>, ParentType, ContextType, Partial<QueryEventsInProcessingArgs>>
268
303
  eventsToProcess?: Resolver<ReadonlyArray<ResolversTypes['Event']>, ParentType, ContextType, Partial<QueryEventsToProcessArgs>>
269
304
  failedEvents?: Resolver<ReadonlyArray<ResolversTypes['Event']>, ParentType, ContextType, Partial<QueryFailedEventsArgs>>
270
305
  variables?: Resolver<ReadonlyArray<ResolversTypes['Variable']>, ParentType, ContextType>
271
306
  }
272
307
 
308
+ export type RetryEventResponseResolvers<ContextType = any, ParentType extends ResolversParentTypes['RetryEventResponse'] = ResolversParentTypes['RetryEventResponse']> = {
309
+ ok?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>
310
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>
311
+ }
312
+
273
313
  export type SetVariablesResponseResolvers<ContextType = any, ParentType extends ResolversParentTypes['SetVariablesResponse'] = ResolversParentTypes['SetVariablesResponse']> = {
274
314
  ok?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>
275
315
  __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>
276
316
  }
277
317
 
318
+ export type StopEventResponseResolvers<ContextType = any, ParentType extends ResolversParentTypes['StopEventResponse'] = ResolversParentTypes['StopEventResponse']> = {
319
+ ok?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>
320
+ __isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>
321
+ }
322
+
278
323
  export interface UuidScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['Uuid'], any> {
279
324
  name: 'Uuid'
280
325
  }
@@ -292,7 +337,9 @@ export type Resolvers<ContextType = any> = {
292
337
  Mutation?: MutationResolvers<ContextType>
293
338
  ProcessBatchResponse?: ProcessBatchResponseResolvers<ContextType>
294
339
  Query?: QueryResolvers<ContextType>
340
+ RetryEventResponse?: RetryEventResponseResolvers<ContextType>
295
341
  SetVariablesResponse?: SetVariablesResponseResolvers<ContextType>
342
+ StopEventResponse?: StopEventResponseResolvers<ContextType>
296
343
  Uuid?: GraphQLScalarType
297
344
  Variable?: VariableResolvers<ContextType>
298
345
  }
package/src/index.ts CHANGED
@@ -7,7 +7,7 @@ import { MasterContainerBuilder, MasterContainerHook } from '@contember/engine-h
7
7
  import { ActionsApiMiddlewareFactory } from './graphql/http/ActionsApiMiddlewareFactory'
8
8
  import { ActionsGraphQLHandlerFactory } from './graphql/http/ActionsGraphQLHandlerFactory'
9
9
  import { ResolversFactory } from './graphql/resolvers/ResolversFactory'
10
- import { EventsQueryResolver, ProcessBatchMutationResolver, SetVariablesMutationResolver } from './graphql/resolvers'
10
+ import { EventsQueryResolver, ProcessBatchMutationResolver, RetryEventMutationResolver, SetVariablesMutationResolver, StopEventMutationResolver } from './graphql/resolvers'
11
11
  import { EventDispatcher } from './dispatch/EventDispatcher'
12
12
  import { EventsRepository } from './dispatch/EventsRepository'
13
13
  import { TargetHandlerResolver } from './dispatch/TargetHandlerResolver'
@@ -50,11 +50,13 @@ export default class ActionsPlugin implements Plugin {
50
50
  .addService('actions_variableManager', () => {
51
51
  return new VariablesManager()
52
52
  })
53
- .addService('actions_eventDispatcher', ({ actions_variableManager }) => {
54
- const eventsRepository = new EventsRepository()
53
+ .addService('actions_eventRepository', () => {
54
+ return new EventsRepository()
55
+ })
56
+ .addService('actions_eventDispatcher', ({ actions_eventRepository, actions_variableManager }) => {
55
57
  const webhookTargetHandler = new WebhookTargetHandler(new WebhookFetcherNative())
56
58
  const targetHandlerResolver = new TargetHandlerResolver(webhookTargetHandler)
57
- return new EventDispatcher(eventsRepository, actions_variableManager, targetHandlerResolver)
59
+ return new EventDispatcher(actions_eventRepository, actions_variableManager, targetHandlerResolver)
58
60
  })
59
61
  .addService('actions_dispatchWorkerSupervisorFactory', ({ actions_eventDispatcher }) => {
60
62
  const projectDispatcherFactory = new ProjectDispatcherFactory(actions_eventDispatcher)
@@ -63,7 +65,7 @@ export default class ActionsPlugin implements Plugin {
63
65
  .addService('actions_authorizator', () => {
64
66
  return new Authorizator.Default(new AccessEvaluator.PermissionEvaluator(new ActionsPermissionsFactory().create()))
65
67
  })
66
- .setupService('application', (it, { projectContextResolver, debugMode, actions_eventDispatcher, actions_dispatchWorkerSupervisorFactory, actions_variableManager, actions_authorizator }) => {
68
+ .setupService('application', (it, { projectContextResolver, debugMode, actions_eventRepository, actions_eventDispatcher, actions_dispatchWorkerSupervisorFactory, actions_variableManager, actions_authorizator }) => {
67
69
  const handlerFactory = new ActionsGraphQLHandlerFactory()
68
70
  const eventsQueryResolver = new EventsQueryResolver()
69
71
  const processBatchMutationResolver = new ProcessBatchMutationResolver(actions_eventDispatcher)
@@ -74,6 +76,8 @@ export default class ActionsPlugin implements Plugin {
74
76
  processBatchMutationResolver,
75
77
  variablesQueryResolver,
76
78
  setVariablesMutationResolver,
79
+ new RetryEventMutationResolver(actions_eventRepository),
80
+ new StopEventMutationResolver(actions_eventRepository),
77
81
  )
78
82
 
79
83
  const actionsContextResolver = new ActionsContextResolver(debugMode, projectContextResolver)
@@ -0,0 +1,21 @@
1
+ import { DatabaseQuery, DatabaseQueryable, SelectBuilder } from '@contember/database'
2
+ import { EventRow } from './types'
3
+
4
+ export class EventByIdQuery extends DatabaseQuery<EventRow | null> {
5
+ constructor(
6
+ private readonly id: string,
7
+ ) {
8
+ super()
9
+ }
10
+
11
+ async fetch(queryable: DatabaseQueryable): Promise<EventRow | null> {
12
+ const result = await SelectBuilder.create<EventRow>()
13
+ .from('actions_event')
14
+ .select('*')
15
+ .where({
16
+ id: this.id,
17
+ })
18
+ .getResult(queryable.db)
19
+ return this.fetchOneOrNull(result)
20
+ }
21
+ }
@@ -2,8 +2,9 @@ import { Client, InsertBuilder } from '@contember/database'
2
2
  import { Mapper } from '@contember/engine-content-api'
3
3
  import { Actions, ActionsPayload } from '@contember/schema'
4
4
  import { EventRow } from '../model/types'
5
+ import { notify } from '../utils/notifyChannel'
6
+
5
7
 
6
- export const NOTIFY_CHANNEL_NAME = 'actions_event'
7
8
  type EventRowToInsert = Omit<EventRow, 'created_at' | 'visible_at' | 'last_state_change' | 'log'> & {
8
9
  created_at: string | Date
9
10
  visible_at: string | Date
@@ -49,6 +50,6 @@ export class TriggerPayloadPersister {
49
50
  .execute(this.client)
50
51
  }
51
52
 
52
- await this.client.query('SELECT pg_notify(?, ?)', [NOTIFY_CHANNEL_NAME, this.projectSlug])
53
+ await notify(this.client, this.projectSlug)
53
54
  }
54
55
  }
@@ -0,0 +1,6 @@
1
+ import { Client } from '@contember/database'
2
+
3
+ export const NOTIFY_CHANNEL_NAME = 'actions_event'
4
+ export const notify = async (db: Client, projectSlug: string) => {
5
+ await db.query('SELECT pg_notify(?, ?)', [NOTIFY_CHANNEL_NAME, projectSlug])
6
+ }