@backstage/plugin-events-backend-module-google-pubsub 0.2.2-next.1 → 0.2.2-next.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @backstage/plugin-events-backend-module-google-pubsub
2
2
 
3
+ ## 0.2.2-next.2
4
+
5
+ ### Patch Changes
6
+
7
+ - eacf362: Migrated internal metrics in `GooglePubSubConsumingEventPublisher` and `EventConsumingGooglePubSubPublisher` to use the new alpha `MetricsService`
8
+ - Updated dependencies
9
+ - @backstage/errors@1.3.0-next.0
10
+ - @backstage/backend-plugin-api@1.9.0-next.2
11
+ - @backstage/config@1.3.7-next.0
12
+ - @backstage/filter-predicates@0.1.2-next.0
13
+ - @backstage/plugin-events-node@0.4.21-next.2
14
+
3
15
  ## 0.2.2-next.1
4
16
 
5
17
  ### Patch Changes
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var pubsub = require('@google-cloud/pubsub');
4
- var api = require('@opentelemetry/api');
5
4
  var config = require('./config.cjs.js');
6
5
 
7
6
  class EventConsumingGooglePubSubPublisher {
@@ -15,6 +14,7 @@ class EventConsumingGooglePubSubPublisher {
15
14
  const publisher = new EventConsumingGooglePubSubPublisher({
16
15
  logger: options.logger,
17
16
  events: options.events,
17
+ metrics: options.metrics,
18
18
  tasks: config.readSubscriptionTasksFromConfig(options.config),
19
19
  pubSubFactory: (projectId) => new pubsub.PubSub({ projectId })
20
20
  });
@@ -31,13 +31,12 @@ class EventConsumingGooglePubSubPublisher {
31
31
  this.#events = options.events;
32
32
  this.#tasks = options.tasks;
33
33
  this.#pubSubFactory = options.pubSubFactory;
34
- const meter = api.metrics.getMeter("default");
35
34
  this.#metrics = {
36
- messages: meter.createCounter(
35
+ messages: options.metrics.createCounter(
37
36
  "events.google.pubsub.publisher.messages.total",
38
37
  {
39
38
  description: "Number of Pub/Sub messages sent by EventConsumingGooglePubSubPublisher",
40
- unit: "short"
39
+ unit: "{message}"
41
40
  }
42
41
  )
43
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EventConsumingGooglePubSubPublisher.cjs.js","sources":["../../src/EventConsumingGooglePubSubPublisher/EventConsumingGooglePubSubPublisher.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n} from '@backstage/backend-plugin-api';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { PubSub } from '@google-cloud/pubsub';\nimport { Counter, metrics } from '@opentelemetry/api';\nimport { readSubscriptionTasksFromConfig } from './config';\nimport { EventContext, SubscriptionTask } from './types';\nimport { JsonValue } from '@backstage/types';\n\n/**\n * Reads messages off of the events system and forwards them into Google Pub/Sub\n * topics.\n */\nexport class EventConsumingGooglePubSubPublisher {\n readonly #logger: LoggerService;\n readonly #events: EventsService;\n readonly #tasks: SubscriptionTask[];\n readonly #pubSubFactory: (projectId: string) => PubSub;\n readonly #metrics: { messages: Counter };\n #activeClientsByProjectId: Map<string, PubSub>;\n\n static create(options: {\n config: RootConfigService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n events: EventsService;\n }) {\n const publisher = new EventConsumingGooglePubSubPublisher({\n logger: options.logger,\n events: options.events,\n tasks: readSubscriptionTasksFromConfig(options.config),\n pubSubFactory: projectId => new PubSub({ projectId }),\n });\n\n options.rootLifecycle.addStartupHook(async () => {\n await publisher.start();\n });\n\n options.rootLifecycle.addBeforeShutdownHook(async () => {\n await publisher.stop();\n });\n\n return publisher;\n }\n\n constructor(options: {\n logger: LoggerService;\n events: EventsService;\n tasks: SubscriptionTask[];\n pubSubFactory: (projectId: string) => PubSub;\n }) {\n this.#logger = options.logger;\n this.#events = options.events;\n this.#tasks = options.tasks;\n this.#pubSubFactory = options.pubSubFactory;\n\n const meter = metrics.getMeter('default');\n this.#metrics = {\n messages: meter.createCounter(\n 'events.google.pubsub.publisher.messages.total',\n {\n description:\n 'Number of Pub/Sub messages sent by EventConsumingGooglePubSubPublisher',\n unit: 'short',\n },\n ),\n };\n\n this.#activeClientsByProjectId = new Map();\n }\n\n async start() {\n for (const task of this.#tasks) {\n this.#logger.info(\n `Starting publisher: id=${\n task.id\n } sourceTopics=${task.sourceTopics.join(',')} targetTopic=${\n task.targetTopicPattern\n }`,\n );\n\n await this.#events.subscribe({\n id: `EventConsumingGooglePubSubPublisher.${task.id}`,\n topics: task.sourceTopics,\n onEvent: async event => {\n let status: 'success' | 'failed' | 'ignored' = 'failed';\n try {\n const context: EventContext = {\n event: {\n topic: event.topic,\n eventPayload: event.eventPayload as JsonValue,\n metadata: event.metadata,\n },\n };\n\n if (!task.filter(context)) {\n status = 'ignored';\n return;\n }\n\n const topic = task.mapToTopic(context);\n if (!topic) {\n status = 'ignored';\n return;\n }\n\n let pubsub = this.#activeClientsByProjectId.get(topic.project);\n if (!pubsub) {\n pubsub = this.#pubSubFactory(topic.project);\n this.#activeClientsByProjectId.set(topic.project, pubsub);\n }\n\n await pubsub.topic(topic.topic).publishMessage({\n json: event.eventPayload,\n attributes: task.mapToAttributes(context),\n });\n\n status = 'success';\n } catch (error) {\n this.#logger.error(\n 'Error publishing Google Pub/Sub message',\n error,\n );\n status = 'failed';\n throw error;\n } finally {\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: status,\n });\n }\n },\n });\n }\n }\n\n async stop() {\n const clients = Array.from(this.#activeClientsByProjectId.values());\n this.#activeClientsByProjectId = new Map();\n\n await Promise.allSettled(\n clients.map(async client => {\n this.#logger.info(`Closing Google Pub/Sub client: ${client.projectId}`);\n await client.close();\n }),\n );\n }\n}\n"],"names":["readSubscriptionTasksFromConfig","PubSub","metrics"],"mappings":"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"}
1
+ {"version":3,"file":"EventConsumingGooglePubSubPublisher.cjs.js","sources":["../../src/EventConsumingGooglePubSubPublisher/EventConsumingGooglePubSubPublisher.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n} from '@backstage/backend-plugin-api';\nimport { EventsService } from '@backstage/plugin-events-node';\nimport { PubSub } from '@google-cloud/pubsub';\nimport type {\n MetricsService,\n MetricsServiceCounter,\n} from '@backstage/backend-plugin-api/alpha';\nimport { readSubscriptionTasksFromConfig } from './config';\nimport { EventContext, SubscriptionTask } from './types';\nimport { JsonValue } from '@backstage/types';\n\n/**\n * Reads messages off of the events system and forwards them into Google Pub/Sub\n * topics.\n */\nexport class EventConsumingGooglePubSubPublisher {\n readonly #logger: LoggerService;\n readonly #events: EventsService;\n readonly #tasks: SubscriptionTask[];\n readonly #pubSubFactory: (projectId: string) => PubSub;\n readonly #metrics: {\n messages: MetricsServiceCounter<{ subscription: string; status: string }>;\n };\n #activeClientsByProjectId: Map<string, PubSub>;\n\n static create(options: {\n config: RootConfigService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n events: EventsService;\n metrics: MetricsService;\n }) {\n const publisher = new EventConsumingGooglePubSubPublisher({\n logger: options.logger,\n events: options.events,\n metrics: options.metrics,\n tasks: readSubscriptionTasksFromConfig(options.config),\n pubSubFactory: projectId => new PubSub({ projectId }),\n });\n\n options.rootLifecycle.addStartupHook(async () => {\n await publisher.start();\n });\n\n options.rootLifecycle.addBeforeShutdownHook(async () => {\n await publisher.stop();\n });\n\n return publisher;\n }\n\n constructor(options: {\n logger: LoggerService;\n events: EventsService;\n metrics: MetricsService;\n tasks: SubscriptionTask[];\n pubSubFactory: (projectId: string) => PubSub;\n }) {\n this.#logger = options.logger;\n this.#events = options.events;\n this.#tasks = options.tasks;\n this.#pubSubFactory = options.pubSubFactory;\n\n this.#metrics = {\n messages: options.metrics.createCounter(\n 'events.google.pubsub.publisher.messages.total',\n {\n description:\n 'Number of Pub/Sub messages sent by EventConsumingGooglePubSubPublisher',\n unit: '{message}',\n },\n ),\n };\n\n this.#activeClientsByProjectId = new Map();\n }\n\n async start() {\n for (const task of this.#tasks) {\n this.#logger.info(\n `Starting publisher: id=${\n task.id\n } sourceTopics=${task.sourceTopics.join(',')} targetTopic=${\n task.targetTopicPattern\n }`,\n );\n\n await this.#events.subscribe({\n id: `EventConsumingGooglePubSubPublisher.${task.id}`,\n topics: task.sourceTopics,\n onEvent: async event => {\n let status: 'success' | 'failed' | 'ignored' = 'failed';\n try {\n const context: EventContext = {\n event: {\n topic: event.topic,\n eventPayload: event.eventPayload as JsonValue,\n metadata: event.metadata,\n },\n };\n\n if (!task.filter(context)) {\n status = 'ignored';\n return;\n }\n\n const topic = task.mapToTopic(context);\n if (!topic) {\n status = 'ignored';\n return;\n }\n\n let pubsub = this.#activeClientsByProjectId.get(topic.project);\n if (!pubsub) {\n pubsub = this.#pubSubFactory(topic.project);\n this.#activeClientsByProjectId.set(topic.project, pubsub);\n }\n\n await pubsub.topic(topic.topic).publishMessage({\n json: event.eventPayload,\n attributes: task.mapToAttributes(context),\n });\n\n status = 'success';\n } catch (error) {\n this.#logger.error(\n 'Error publishing Google Pub/Sub message',\n error,\n );\n status = 'failed';\n throw error;\n } finally {\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: status,\n });\n }\n },\n });\n }\n }\n\n async stop() {\n const clients = Array.from(this.#activeClientsByProjectId.values());\n this.#activeClientsByProjectId = new Map();\n\n await Promise.allSettled(\n clients.map(async client => {\n this.#logger.info(`Closing Google Pub/Sub client: ${client.projectId}`);\n await client.close();\n }),\n );\n }\n}\n"],"names":["readSubscriptionTasksFromConfig","PubSub"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var alpha = require('@backstage/backend-plugin-api/alpha');
4
5
  var pluginEventsNode = require('@backstage/plugin-events-node');
5
6
  var EventConsumingGooglePubSubPublisher = require('./EventConsumingGooglePubSubPublisher.cjs.js');
6
7
 
@@ -13,14 +14,16 @@ const eventsModuleEventConsumingGooglePubSubPublisher = backendPluginApi.createB
13
14
  config: backendPluginApi.coreServices.rootConfig,
14
15
  logger: backendPluginApi.coreServices.logger,
15
16
  rootLifecycle: backendPluginApi.coreServices.rootLifecycle,
16
- events: pluginEventsNode.eventsServiceRef
17
+ events: pluginEventsNode.eventsServiceRef,
18
+ metrics: alpha.metricsServiceRef
17
19
  },
18
- async init({ config, logger, rootLifecycle, events }) {
20
+ async init({ config, logger, rootLifecycle, events, metrics }) {
19
21
  EventConsumingGooglePubSubPublisher.EventConsumingGooglePubSubPublisher.create({
20
22
  config,
21
23
  logger,
22
24
  rootLifecycle,
23
- events
25
+ events,
26
+ metrics
24
27
  });
25
28
  }
26
29
  });
@@ -1 +1 @@
1
- {"version":3,"file":"module.cjs.js","sources":["../../src/EventConsumingGooglePubSubPublisher/module.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { EventConsumingGooglePubSubPublisher } from './EventConsumingGooglePubSubPublisher';\n\n/**\n * Reads messages off of the events system and forwards them into Google Pub/Sub\n * topics.\n *\n * @public\n */\nexport const eventsModuleEventConsumingGooglePubSubPublisher =\n createBackendModule({\n pluginId: 'events',\n moduleId: 'event-consuming-google-pubsub-publisher',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n rootLifecycle: coreServices.rootLifecycle,\n events: eventsServiceRef,\n },\n async init({ config, logger, rootLifecycle, events }) {\n EventConsumingGooglePubSubPublisher.create({\n config,\n logger,\n rootLifecycle,\n events,\n });\n },\n });\n },\n });\n"],"names":["createBackendModule","coreServices","eventsServiceRef","EventConsumingGooglePubSubPublisher"],"mappings":";;;;;;AA6BO,MAAM,kDACXA,oCAAA,CAAoB;AAAA,EAClB,QAAA,EAAU,QAAA;AAAA,EACV,QAAA,EAAU,yCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,QACrB,eAAeA,6BAAA,CAAa,aAAA;AAAA,QAC5B,MAAA,EAAQC;AAAA,OACV;AAAA,MACA,MAAM,IAAA,CAAK,EAAE,QAAQ,MAAA,EAAQ,aAAA,EAAe,QAAO,EAAG;AACpD,QAAAC,uEAAA,CAAoC,MAAA,CAAO;AAAA,UACzC,MAAA;AAAA,UACA,MAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"module.cjs.js","sources":["../../src/EventConsumingGooglePubSubPublisher/module.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { metricsServiceRef } from '@backstage/backend-plugin-api/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { EventConsumingGooglePubSubPublisher } from './EventConsumingGooglePubSubPublisher';\n\n/**\n * Reads messages off of the events system and forwards them into Google Pub/Sub\n * topics.\n *\n * @public\n */\nexport const eventsModuleEventConsumingGooglePubSubPublisher =\n createBackendModule({\n pluginId: 'events',\n moduleId: 'event-consuming-google-pubsub-publisher',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n rootLifecycle: coreServices.rootLifecycle,\n events: eventsServiceRef,\n metrics: metricsServiceRef,\n },\n async init({ config, logger, rootLifecycle, events, metrics }) {\n EventConsumingGooglePubSubPublisher.create({\n config,\n logger,\n rootLifecycle,\n events,\n metrics,\n });\n },\n });\n },\n });\n"],"names":["createBackendModule","coreServices","eventsServiceRef","metricsServiceRef","EventConsumingGooglePubSubPublisher"],"mappings":";;;;;;;AA8BO,MAAM,kDACXA,oCAAA,CAAoB;AAAA,EAClB,QAAA,EAAU,QAAA;AAAA,EACV,QAAA,EAAU,yCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,QACrB,eAAeA,6BAAA,CAAa,aAAA;AAAA,QAC5B,MAAA,EAAQC,iCAAA;AAAA,QACR,OAAA,EAASC;AAAA,OACX;AAAA,MACA,MAAM,KAAK,EAAE,MAAA,EAAQ,QAAQ,aAAA,EAAe,MAAA,EAAQ,SAAQ,EAAG;AAC7D,QAAAC,uEAAA,CAAoC,MAAA,CAAO;AAAA,UACzC,MAAA;AAAA,UACA,MAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -2,7 +2,6 @@
2
2
 
3
3
  var errors = require('@backstage/errors');
4
4
  var pubsub = require('@google-cloud/pubsub');
5
- var api = require('@opentelemetry/api');
6
5
  var config = require('./config.cjs.js');
7
6
 
8
7
  class GooglePubSubConsumingEventPublisher {
@@ -17,6 +16,7 @@ class GooglePubSubConsumingEventPublisher {
17
16
  const publisher = new GooglePubSubConsumingEventPublisher({
18
17
  logger: options.logger,
19
18
  events: options.events,
19
+ metrics: options.metrics,
20
20
  tasks: config.readSubscriptionTasksFromConfig(options.config),
21
21
  pubSubFactory: (projectId) => new pubsub.PubSub({ projectId })
22
22
  });
@@ -33,13 +33,12 @@ class GooglePubSubConsumingEventPublisher {
33
33
  this.#events = options.events;
34
34
  this.#tasks = options.tasks;
35
35
  this.#pubSubFactory = options.pubSubFactory;
36
- const meter = api.metrics.getMeter("default");
37
36
  this.#metrics = {
38
- messages: meter.createCounter(
37
+ messages: options.metrics.createCounter(
39
38
  "events.google.pubsub.consumer.messages.total",
40
39
  {
41
40
  description: "Number of Pub/Sub messages received by GooglePubSubConsumingEventPublisher",
42
- unit: "short"
41
+ unit: "{message}"
43
42
  }
44
43
  )
45
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GooglePubSubConsumingEventPublisher.cjs.js","sources":["../../src/GooglePubSubConsumingEventPublisher/GooglePubSubConsumingEventPublisher.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n} from '@backstage/backend-plugin-api';\nimport { ForwardedError } from '@backstage/errors';\nimport { EventParams, EventsService } from '@backstage/plugin-events-node';\nimport { JsonValue } from '@backstage/types';\nimport { Message, PubSub, Subscription } from '@google-cloud/pubsub';\nimport { Counter, metrics } from '@opentelemetry/api';\nimport { readSubscriptionTasksFromConfig } from './config';\nimport { MessageContext, SubscriptionTask } from './types';\n\n/**\n * Reads messages off of Google Pub/Sub subscriptions and forwards them into the\n * Backstage events system.\n */\nexport class GooglePubSubConsumingEventPublisher {\n readonly #logger: LoggerService;\n readonly #events: EventsService;\n readonly #tasks: SubscriptionTask[];\n readonly #pubSubFactory: (projectId: string) => PubSub;\n readonly #metrics: { messages: Counter };\n #activeClientsByProjectId: Map<string, PubSub>;\n #activeSubscriptions: Subscription[];\n\n static create(options: {\n config: RootConfigService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n events: EventsService;\n }) {\n const publisher = new GooglePubSubConsumingEventPublisher({\n logger: options.logger,\n events: options.events,\n tasks: readSubscriptionTasksFromConfig(options.config),\n pubSubFactory: projectId => new PubSub({ projectId }),\n });\n\n options.rootLifecycle.addStartupHook(async () => {\n await publisher.start();\n });\n\n options.rootLifecycle.addBeforeShutdownHook(async () => {\n await publisher.stop();\n });\n\n return publisher;\n }\n\n constructor(options: {\n logger: LoggerService;\n events: EventsService;\n tasks: SubscriptionTask[];\n pubSubFactory: (projectId: string) => PubSub;\n }) {\n this.#logger = options.logger;\n this.#events = options.events;\n this.#tasks = options.tasks;\n this.#pubSubFactory = options.pubSubFactory;\n\n const meter = metrics.getMeter('default');\n this.#metrics = {\n messages: meter.createCounter(\n 'events.google.pubsub.consumer.messages.total',\n {\n description:\n 'Number of Pub/Sub messages received by GooglePubSubConsumingEventPublisher',\n unit: 'short',\n },\n ),\n };\n\n this.#activeClientsByProjectId = new Map();\n this.#activeSubscriptions = [];\n }\n\n async start() {\n for (const task of this.#tasks) {\n this.#logger.info(\n `Starting subscription: id=${task.id} project=${task.project} subscription=${task.subscription}`,\n );\n\n let pubsub = this.#activeClientsByProjectId.get(task.project);\n if (!pubsub) {\n pubsub = this.#pubSubFactory(task.project);\n this.#activeClientsByProjectId.set(task.project, pubsub);\n }\n\n // You cannot control the actual batch size delivered to the client from\n // pubsub, so these settings actually instead control the rate at which\n // messages are released to our event handlers by the pubsub library. This\n // means that there may be significantly more than maxMessages messages\n // pending in memory before we see them. Thus, the settings here are rather\n // chosen so as to limit the concurrency of hammering consumers (the catalog\n // etc).\n const subscription = pubsub.subscription(task.subscription, {\n flowControl: {\n maxMessages: 5,\n allowExcessMessages: false,\n },\n });\n\n this.#activeSubscriptions.push(subscription);\n\n subscription.on('error', error => {\n this.#logger.error(\n `Error reading Google Pub/Sub subscription: ${task.id}`,\n error,\n );\n });\n\n subscription.on('message', async message => {\n let event: EventParams;\n try {\n event = this.#messageToEvent(message, task)!;\n if (!event) {\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'ignored',\n });\n return;\n }\n } catch (error) {\n this.#logger.error('Error processing Google Pub/Sub message', error);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'failed',\n });\n // We unconditionally ACK the message in this case, because if it's\n // broken, it will still be broken next time around, so there is no\n // point in re-delivering it.\n message.ack();\n return;\n }\n\n try {\n await this.#events.publish(event);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'success',\n });\n message.ack();\n } catch (error) {\n this.#logger.error('Error processing Google Pub/Sub message', error);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'failed',\n });\n // We fast-NACK the message in this case because this may be a\n // transient problem with the events backend.\n message.nack();\n }\n });\n }\n }\n\n async stop() {\n const subscriptions = this.#activeSubscriptions;\n const clients = Array.from(this.#activeClientsByProjectId.values());\n\n this.#activeSubscriptions = [];\n this.#activeClientsByProjectId = new Map();\n\n await Promise.allSettled(\n subscriptions.map(async subscription => {\n this.#logger.info(\n `Closing Google Pub/Sub subscription: ${subscription.name}`,\n );\n await subscription.close();\n }),\n );\n\n await Promise.allSettled(\n clients.map(async client => {\n this.#logger.info(`Closing Google Pub/Sub client: ${client.projectId}`);\n await client.close();\n }),\n );\n }\n\n #messageToEvent(\n message: Message,\n task: SubscriptionTask,\n ): EventParams | undefined {\n let eventPayload: JsonValue;\n try {\n eventPayload = JSON.parse(message.data.toString());\n } catch (error) {\n throw new ForwardedError('Payload was not valid JSON', error);\n }\n\n const attributes = message.attributes;\n\n const context: MessageContext = {\n message: {\n data: eventPayload,\n attributes,\n },\n };\n\n if (!task.filter(context)) {\n return undefined;\n }\n\n const topic = task.mapToTopic(context);\n if (!topic) {\n return undefined;\n }\n\n const metadata = task.mapToMetadata(context);\n return {\n topic,\n eventPayload,\n metadata,\n };\n }\n}\n"],"names":["readSubscriptionTasksFromConfig","PubSub","metrics","ForwardedError"],"mappings":"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"}
1
+ {"version":3,"file":"GooglePubSubConsumingEventPublisher.cjs.js","sources":["../../src/GooglePubSubConsumingEventPublisher/GooglePubSubConsumingEventPublisher.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n LoggerService,\n RootConfigService,\n RootLifecycleService,\n} from '@backstage/backend-plugin-api';\nimport { ForwardedError } from '@backstage/errors';\nimport { EventParams, EventsService } from '@backstage/plugin-events-node';\nimport { JsonValue } from '@backstage/types';\nimport { Message, PubSub, Subscription } from '@google-cloud/pubsub';\nimport type {\n MetricsService,\n MetricsServiceCounter,\n} from '@backstage/backend-plugin-api/alpha';\nimport { readSubscriptionTasksFromConfig } from './config';\nimport { MessageContext, SubscriptionTask } from './types';\n\n/**\n * Reads messages off of Google Pub/Sub subscriptions and forwards them into the\n * Backstage events system.\n */\nexport class GooglePubSubConsumingEventPublisher {\n readonly #logger: LoggerService;\n readonly #events: EventsService;\n readonly #tasks: SubscriptionTask[];\n readonly #pubSubFactory: (projectId: string) => PubSub;\n readonly #metrics: {\n messages: MetricsServiceCounter<{ subscription: string; status: string }>;\n };\n #activeClientsByProjectId: Map<string, PubSub>;\n #activeSubscriptions: Subscription[];\n\n static create(options: {\n config: RootConfigService;\n logger: LoggerService;\n rootLifecycle: RootLifecycleService;\n events: EventsService;\n metrics: MetricsService;\n }) {\n const publisher = new GooglePubSubConsumingEventPublisher({\n logger: options.logger,\n events: options.events,\n metrics: options.metrics,\n tasks: readSubscriptionTasksFromConfig(options.config),\n pubSubFactory: projectId => new PubSub({ projectId }),\n });\n\n options.rootLifecycle.addStartupHook(async () => {\n await publisher.start();\n });\n\n options.rootLifecycle.addBeforeShutdownHook(async () => {\n await publisher.stop();\n });\n\n return publisher;\n }\n\n constructor(options: {\n logger: LoggerService;\n events: EventsService;\n metrics: MetricsService;\n tasks: SubscriptionTask[];\n pubSubFactory: (projectId: string) => PubSub;\n }) {\n this.#logger = options.logger;\n this.#events = options.events;\n this.#tasks = options.tasks;\n this.#pubSubFactory = options.pubSubFactory;\n\n this.#metrics = {\n messages: options.metrics.createCounter(\n 'events.google.pubsub.consumer.messages.total',\n {\n description:\n 'Number of Pub/Sub messages received by GooglePubSubConsumingEventPublisher',\n unit: '{message}',\n },\n ),\n };\n\n this.#activeClientsByProjectId = new Map();\n this.#activeSubscriptions = [];\n }\n\n async start() {\n for (const task of this.#tasks) {\n this.#logger.info(\n `Starting subscription: id=${task.id} project=${task.project} subscription=${task.subscription}`,\n );\n\n let pubsub = this.#activeClientsByProjectId.get(task.project);\n if (!pubsub) {\n pubsub = this.#pubSubFactory(task.project);\n this.#activeClientsByProjectId.set(task.project, pubsub);\n }\n\n // You cannot control the actual batch size delivered to the client from\n // pubsub, so these settings actually instead control the rate at which\n // messages are released to our event handlers by the pubsub library. This\n // means that there may be significantly more than maxMessages messages\n // pending in memory before we see them. Thus, the settings here are rather\n // chosen so as to limit the concurrency of hammering consumers (the catalog\n // etc).\n const subscription = pubsub.subscription(task.subscription, {\n flowControl: {\n maxMessages: 5,\n allowExcessMessages: false,\n },\n });\n\n this.#activeSubscriptions.push(subscription);\n\n subscription.on('error', error => {\n this.#logger.error(\n `Error reading Google Pub/Sub subscription: ${task.id}`,\n error,\n );\n });\n\n subscription.on('message', async message => {\n let event: EventParams;\n try {\n event = this.#messageToEvent(message, task)!;\n if (!event) {\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'ignored',\n });\n return;\n }\n } catch (error) {\n this.#logger.error('Error processing Google Pub/Sub message', error);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'failed',\n });\n // We unconditionally ACK the message in this case, because if it's\n // broken, it will still be broken next time around, so there is no\n // point in re-delivering it.\n message.ack();\n return;\n }\n\n try {\n await this.#events.publish(event);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'success',\n });\n message.ack();\n } catch (error) {\n this.#logger.error('Error processing Google Pub/Sub message', error);\n this.#metrics.messages.add(1, {\n subscription: task.id,\n status: 'failed',\n });\n // We fast-NACK the message in this case because this may be a\n // transient problem with the events backend.\n message.nack();\n }\n });\n }\n }\n\n async stop() {\n const subscriptions = this.#activeSubscriptions;\n const clients = Array.from(this.#activeClientsByProjectId.values());\n\n this.#activeSubscriptions = [];\n this.#activeClientsByProjectId = new Map();\n\n await Promise.allSettled(\n subscriptions.map(async subscription => {\n this.#logger.info(\n `Closing Google Pub/Sub subscription: ${subscription.name}`,\n );\n await subscription.close();\n }),\n );\n\n await Promise.allSettled(\n clients.map(async client => {\n this.#logger.info(`Closing Google Pub/Sub client: ${client.projectId}`);\n await client.close();\n }),\n );\n }\n\n #messageToEvent(\n message: Message,\n task: SubscriptionTask,\n ): EventParams | undefined {\n let eventPayload: JsonValue;\n try {\n eventPayload = JSON.parse(message.data.toString());\n } catch (error) {\n throw new ForwardedError('Payload was not valid JSON', error);\n }\n\n const attributes = message.attributes;\n\n const context: MessageContext = {\n message: {\n data: eventPayload,\n attributes,\n },\n };\n\n if (!task.filter(context)) {\n return undefined;\n }\n\n const topic = task.mapToTopic(context);\n if (!topic) {\n return undefined;\n }\n\n const metadata = task.mapToMetadata(context);\n return {\n topic,\n eventPayload,\n metadata,\n };\n }\n}\n"],"names":["readSubscriptionTasksFromConfig","PubSub","ForwardedError"],"mappings":";;;;;;AAoCO,MAAM,mCAAA,CAAoC;AAAA,EACtC,OAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EAGT,yBAAA;AAAA,EACA,oBAAA;AAAA,EAEA,OAAO,OAAO,OAAA,EAMX;AACD,IAAA,MAAM,SAAA,GAAY,IAAI,mCAAA,CAAoC;AAAA,MACxD,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,KAAA,EAAOA,sCAAA,CAAgC,OAAA,CAAQ,MAAM,CAAA;AAAA,MACrD,eAAe,CAAA,SAAA,KAAa,IAAIC,aAAA,CAAO,EAAE,WAAW;AAAA,KACrD,CAAA;AAED,IAAA,OAAA,CAAQ,aAAA,CAAc,eAAe,YAAY;AAC/C,MAAA,MAAM,UAAU,KAAA,EAAM;AAAA,IACxB,CAAC,CAAA;AAED,IAAA,OAAA,CAAQ,aAAA,CAAc,sBAAsB,YAAY;AACtD,MAAA,MAAM,UAAU,IAAA,EAAK;AAAA,IACvB,CAAC,CAAA;AAED,IAAA,OAAO,SAAA;AAAA,EACT;AAAA,EAEA,YAAY,OAAA,EAMT;AACD,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,MAAA;AACvB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,MAAA;AACvB,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,KAAA;AACtB,IAAA,IAAA,CAAK,iBAAiB,OAAA,CAAQ,aAAA;AAE9B,IAAA,IAAA,CAAK,QAAA,GAAW;AAAA,MACd,QAAA,EAAU,QAAQ,OAAA,CAAQ,aAAA;AAAA,QACxB,8CAAA;AAAA,QACA;AAAA,UACE,WAAA,EACE,4EAAA;AAAA,UACF,IAAA,EAAM;AAAA;AACR;AACF,KACF;AAEA,IAAA,IAAA,CAAK,yBAAA,uBAAgC,GAAA,EAAI;AACzC,IAAA,IAAA,CAAK,uBAAuB,EAAC;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAA,GAAQ;AACZ,IAAA,KAAA,MAAW,IAAA,IAAQ,KAAK,MAAA,EAAQ;AAC9B,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,QACX,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,SAAA,EAAY,KAAK,OAAO,CAAA,cAAA,EAAiB,KAAK,YAAY,CAAA;AAAA,OAChG;AAEA,MAAA,IAAI,MAAA,GAAS,IAAA,CAAK,yBAAA,CAA0B,GAAA,CAAI,KAAK,OAAO,CAAA;AAC5D,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,OAAO,CAAA;AACzC,QAAA,IAAA,CAAK,yBAAA,CAA0B,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS,MAAM,CAAA;AAAA,MACzD;AASA,MAAA,MAAM,YAAA,GAAe,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,YAAA,EAAc;AAAA,QAC1D,WAAA,EAAa;AAAA,UACX,WAAA,EAAa,CAAA;AAAA,UACb,mBAAA,EAAqB;AAAA;AACvB,OACD,CAAA;AAED,MAAA,IAAA,CAAK,oBAAA,CAAqB,KAAK,YAAY,CAAA;AAE3C,MAAA,YAAA,CAAa,EAAA,CAAG,SAAS,CAAA,KAAA,KAAS;AAChC,QAAA,IAAA,CAAK,OAAA,CAAQ,KAAA;AAAA,UACX,CAAA,2CAAA,EAA8C,KAAK,EAAE,CAAA,CAAA;AAAA,UACrD;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAED,MAAA,YAAA,CAAa,EAAA,CAAG,SAAA,EAAW,OAAM,OAAA,KAAW;AAC1C,QAAA,IAAI,KAAA;AACJ,QAAA,IAAI;AACF,UAAA,KAAA,GAAQ,IAAA,CAAK,eAAA,CAAgB,OAAA,EAAS,IAAI,CAAA;AAC1C,UAAA,IAAI,CAAC,KAAA,EAAO;AACV,YAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG;AAAA,cAC5B,cAAc,IAAA,CAAK,EAAA;AAAA,cACnB,MAAA,EAAQ;AAAA,aACT,CAAA;AACD,YAAA;AAAA,UACF;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,yCAAA,EAA2C,KAAK,CAAA;AACnE,UAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG;AAAA,YAC5B,cAAc,IAAA,CAAK,EAAA;AAAA,YACnB,MAAA,EAAQ;AAAA,WACT,CAAA;AAID,UAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,UAAA;AAAA,QACF;AAEA,QAAA,IAAI;AACF,UAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,KAAK,CAAA;AAChC,UAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG;AAAA,YAC5B,cAAc,IAAA,CAAK,EAAA;AAAA,YACnB,MAAA,EAAQ;AAAA,WACT,CAAA;AACD,UAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,QACd,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,yCAAA,EAA2C,KAAK,CAAA;AACnE,UAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAA,EAAG;AAAA,YAC5B,cAAc,IAAA,CAAK,EAAA;AAAA,YACnB,MAAA,EAAQ;AAAA,WACT,CAAA;AAGD,UAAA,OAAA,CAAQ,IAAA,EAAK;AAAA,QACf;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,IAAA,GAAO;AACX,IAAA,MAAM,gBAAgB,IAAA,CAAK,oBAAA;AAC3B,IAAA,MAAM,UAAU,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,yBAAA,CAA0B,QAAQ,CAAA;AAElE,IAAA,IAAA,CAAK,uBAAuB,EAAC;AAC7B,IAAA,IAAA,CAAK,yBAAA,uBAAgC,GAAA,EAAI;AAEzC,IAAA,MAAM,OAAA,CAAQ,UAAA;AAAA,MACZ,aAAA,CAAc,GAAA,CAAI,OAAM,YAAA,KAAgB;AACtC,QAAA,IAAA,CAAK,OAAA,CAAQ,IAAA;AAAA,UACX,CAAA,qCAAA,EAAwC,aAAa,IAAI,CAAA;AAAA,SAC3D;AACA,QAAA,MAAM,aAAa,KAAA,EAAM;AAAA,MAC3B,CAAC;AAAA,KACH;AAEA,IAAA,MAAM,OAAA,CAAQ,UAAA;AAAA,MACZ,OAAA,CAAQ,GAAA,CAAI,OAAM,MAAA,KAAU;AAC1B,QAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,CAAA,+BAAA,EAAkC,MAAA,CAAO,SAAS,CAAA,CAAE,CAAA;AACtE,QAAA,MAAM,OAAO,KAAA,EAAM;AAAA,MACrB,CAAC;AAAA,KACH;AAAA,EACF;AAAA,EAEA,eAAA,CACE,SACA,IAAA,EACyB;AACzB,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI;AACF,MAAA,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA;AAAA,IACnD,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAIC,qBAAA,CAAe,4BAAA,EAA8B,KAAK,CAAA;AAAA,IAC9D;AAEA,IAAA,MAAM,aAAa,OAAA,CAAQ,UAAA;AAE3B,IAAA,MAAM,OAAA,GAA0B;AAAA,MAC9B,OAAA,EAAS;AAAA,QACP,IAAA,EAAM,YAAA;AAAA,QACN;AAAA;AACF,KACF;AAEA,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AACzB,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA;AACrC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA;AAC3C,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AACF;;;;"}
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var alpha = require('@backstage/backend-plugin-api/alpha');
4
5
  var pluginEventsNode = require('@backstage/plugin-events-node');
5
6
  var GooglePubSubConsumingEventPublisher = require('./GooglePubSubConsumingEventPublisher.cjs.js');
6
7
 
@@ -13,14 +14,16 @@ const eventsModuleGooglePubsubConsumingEventPublisher = backendPluginApi.createB
13
14
  config: backendPluginApi.coreServices.rootConfig,
14
15
  logger: backendPluginApi.coreServices.logger,
15
16
  rootLifecycle: backendPluginApi.coreServices.rootLifecycle,
16
- events: pluginEventsNode.eventsServiceRef
17
+ events: pluginEventsNode.eventsServiceRef,
18
+ metrics: alpha.metricsServiceRef
17
19
  },
18
- async init({ config, logger, rootLifecycle, events }) {
20
+ async init({ config, logger, rootLifecycle, events, metrics }) {
19
21
  GooglePubSubConsumingEventPublisher.GooglePubSubConsumingEventPublisher.create({
20
22
  config,
21
23
  logger,
22
24
  rootLifecycle,
23
- events
25
+ events,
26
+ metrics
24
27
  });
25
28
  }
26
29
  });
@@ -1 +1 @@
1
- {"version":3,"file":"module.cjs.js","sources":["../../src/GooglePubSubConsumingEventPublisher/module.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { GooglePubSubConsumingEventPublisher } from './GooglePubSubConsumingEventPublisher';\n\n/**\n * Reads messages off of Google Pub/Sub subscriptions and forwards them into the\n * Backstage events system.\n */\nexport const eventsModuleGooglePubsubConsumingEventPublisher =\n createBackendModule({\n pluginId: 'events',\n moduleId: 'google-pubsub-consuming-event-publisher',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n rootLifecycle: coreServices.rootLifecycle,\n events: eventsServiceRef,\n },\n async init({ config, logger, rootLifecycle, events }) {\n GooglePubSubConsumingEventPublisher.create({\n config,\n logger,\n rootLifecycle,\n events,\n });\n },\n });\n },\n });\n"],"names":["createBackendModule","coreServices","eventsServiceRef","GooglePubSubConsumingEventPublisher"],"mappings":";;;;;;AA2BO,MAAM,kDACXA,oCAAA,CAAoB;AAAA,EAClB,QAAA,EAAU,QAAA;AAAA,EACV,QAAA,EAAU,yCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,QACrB,eAAeA,6BAAA,CAAa,aAAA;AAAA,QAC5B,MAAA,EAAQC;AAAA,OACV;AAAA,MACA,MAAM,IAAA,CAAK,EAAE,QAAQ,MAAA,EAAQ,aAAA,EAAe,QAAO,EAAG;AACpD,QAAAC,uEAAA,CAAoC,MAAA,CAAO;AAAA,UACzC,MAAA;AAAA,UACA,MAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"module.cjs.js","sources":["../../src/GooglePubSubConsumingEventPublisher/module.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { metricsServiceRef } from '@backstage/backend-plugin-api/alpha';\nimport { eventsServiceRef } from '@backstage/plugin-events-node';\nimport { GooglePubSubConsumingEventPublisher } from './GooglePubSubConsumingEventPublisher';\n\n/**\n * Reads messages off of Google Pub/Sub subscriptions and forwards them into the\n * Backstage events system.\n */\nexport const eventsModuleGooglePubsubConsumingEventPublisher =\n createBackendModule({\n pluginId: 'events',\n moduleId: 'google-pubsub-consuming-event-publisher',\n register(reg) {\n reg.registerInit({\n deps: {\n config: coreServices.rootConfig,\n logger: coreServices.logger,\n rootLifecycle: coreServices.rootLifecycle,\n events: eventsServiceRef,\n metrics: metricsServiceRef,\n },\n async init({ config, logger, rootLifecycle, events, metrics }) {\n GooglePubSubConsumingEventPublisher.create({\n config,\n logger,\n rootLifecycle,\n events,\n metrics,\n });\n },\n });\n },\n });\n"],"names":["createBackendModule","coreServices","eventsServiceRef","metricsServiceRef","GooglePubSubConsumingEventPublisher"],"mappings":";;;;;;;AA4BO,MAAM,kDACXA,oCAAA,CAAoB;AAAA,EAClB,QAAA,EAAU,QAAA;AAAA,EACV,QAAA,EAAU,yCAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,UAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,MAAA;AAAA,QACrB,eAAeA,6BAAA,CAAa,aAAA;AAAA,QAC5B,MAAA,EAAQC,iCAAA;AAAA,QACR,OAAA,EAASC;AAAA,OACX;AAAA,MACA,MAAM,KAAK,EAAE,MAAA,EAAQ,QAAQ,aAAA,EAAe,MAAA,EAAQ,SAAQ,EAAG;AAC7D,QAAAC,uEAAA,CAAoC,MAAA,CAAO;AAAA,UACzC,MAAA;AAAA,UACA,MAAA;AAAA,UACA,aAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-events-backend-module-google-pubsub",
3
- "version": "0.2.2-next.1",
3
+ "version": "0.2.2-next.2",
4
4
  "description": "The google-pubsub backend module for the events plugin.",
5
5
  "backstage": {
6
6
  "role": "backend-plugin-module",
@@ -37,20 +37,19 @@
37
37
  "test": "backstage-cli package test"
38
38
  },
39
39
  "dependencies": {
40
- "@backstage/backend-plugin-api": "1.9.0-next.1",
41
- "@backstage/config": "1.3.6",
42
- "@backstage/errors": "1.2.7",
43
- "@backstage/filter-predicates": "0.1.1",
44
- "@backstage/plugin-events-node": "0.4.21-next.1",
40
+ "@backstage/backend-plugin-api": "1.9.0-next.2",
41
+ "@backstage/config": "1.3.7-next.0",
42
+ "@backstage/errors": "1.3.0-next.0",
43
+ "@backstage/filter-predicates": "0.1.2-next.0",
44
+ "@backstage/plugin-events-node": "0.4.21-next.2",
45
45
  "@backstage/types": "1.2.2",
46
- "@google-cloud/pubsub": "^4.10.0",
47
- "@opentelemetry/api": "^1.9.0"
46
+ "@google-cloud/pubsub": "^4.10.0"
48
47
  },
49
48
  "devDependencies": {
50
- "@backstage/backend-defaults": "0.16.1-next.1",
51
- "@backstage/backend-test-utils": "1.11.2-next.1",
52
- "@backstage/cli": "0.36.1-next.1",
53
- "@backstage/plugin-events-backend": "0.6.1-next.1",
49
+ "@backstage/backend-defaults": "0.16.1-next.2",
50
+ "@backstage/backend-test-utils": "1.11.2-next.2",
51
+ "@backstage/cli": "0.36.1-next.2",
52
+ "@backstage/plugin-events-backend": "0.6.1-next.2",
54
53
  "wait-for-expect": "^4.0.0"
55
54
  },
56
55
  "configSchema": "config.d.ts",