nestjs-google-pubsub-microservice icon indicating copy to clipboard operation
nestjs-google-pubsub-microservice copied to clipboard

Decouple subscription creation from topic creation during "init"?

Open ymatsiuk opened this issue 1 year ago • 0 comments

Code:

const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  ApplicationModule,
  {
    strategy: new GCPubSubServer({
      topic: 'projects/ALPHA/topics/FOO',
      subscription: 'projects/BETA/subscriptions/FOO',
      init: true,
      checkExistence: true,
      client: {
        projectId: 'BETA',
      },
    }),
  },
);

Context:

There is a topic FOO in ALPHA project (outside of my team's ownership) that I want to subscribe to from BETA (project my team actually owns). I don't have permissions inside ALPHA except pubsub.topics.attachSubscription. A combination of init=true and checkExistence=true fails with PERMISSION_DENIED (no pubsub.topics.list or pubsub.topics.get), if I flip init to false it also doesn't help since the subscription FOO doesn't exist yet :shrug:

Error

/app/node_modules/@grpc/grpc-js/src/call.ts:82
                     |   const error = new Error(message);
                     |                 ^
                     | Error: 7 PERMISSION_DENIED: User not authorized to perform this action.
                     |     at callErrorFromStatus (/app/node_modules/@grpc/grpc-js/src/call.ts:82:17)
                     |     at Object.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/client.ts:360:55)
                     |     at Object.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/client-interceptors.ts:458:34)
                     |     at Object.onReceiveStatus (/app/node_modules/@grpc/grpc-js/src/client-interceptors.ts:419:48)
                     |     at /app/node_modules/@grpc/grpc-js/src/resolving-call.ts:132:24
                     |     at processTicksAndRejections (node:internal/process/task_queues:77:11)
                     | for call at
                     |     at ServiceClientImpl.makeUnaryRequest (/app/node_modules/@grpc/grpc-js/src/client.ts:325:42)
                     |     at ServiceClientImpl.<anonymous> (/app/node_modules/@grpc/grpc-js/src/make-client.ts:189:15)
                     |     at /app/node_modules/@google-cloud/pubsub/src/v1/publisher_client.ts:307:25
                     |     at /app/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
                     |     at repeat (/app/node_modules/google-gax/build/src/normalCalls/retries.js:80:25)
                     |     at /app/node_modules/google-gax/build/src/normalCalls/retries.js:118:13
                     |     at OngoingCall.call (/app/node_modules/google-gax/build/src/call.js:67:27)
                     |     at NormalApiCaller.call (/app/node_modules/google-gax/build/src/normalCalls/normalApiCaller.js:34:19)
                     |     at /app/node_modules/google-gax/build/src/createApiCall.js:84:30
                     |     at processTicksAndRejections (node:internal/process/task_queues:95:5)

Expected behavior

init and checkExistence moved into topic and subscription so we could make something like this work:

const app = await NestFactory.createMicroservice<MicroserviceOptions>(
  ApplicationModule,
  {
    strategy: new GCPubSubServer({
      topic: {
        name: 'projects/ALPHA/topics/FOO', # <path> might be a better "name" for this
	init: false,
      },
      subscription: {
        name: 'projects/BETA/subscriptions/FOO',
	init: true,
        checkExistence: true,
      },
    }),
  },
);

Alternatively topicInit and subscriptionInit would work as well.

Thanks for all the work you put in nestjs-google-pubsub-microservice :1st_place_medal: :rocket:

ymatsiuk avatar Dec 19 '23 09:12 ymatsiuk