Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better way to get QueueEventsListener method types #2181

Open
1 task done
Mnigos opened this issue Jul 30, 2024 · 1 comment
Open
1 task done

Better way to get QueueEventsListener method types #2181

Mnigos opened this issue Jul 30, 2024 · 1 comment
Labels

Comments

@Mnigos
Copy link

Mnigos commented Jul 30, 2024

Is there an existing issue that is already proposing this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe it

I have created a QueueEvents listener and method parameter types are not inferred correctly which causes passing wrong parameters to the listener definition.

I found a way to get this listener typed, but the solution is not the best

import {
  OnQueueEvent,
  QueueEventsHost,
  QueueEventsListener,
} from '@nestjs/bullmq'
import { QueueEventsListener as IQueueEventsListener } from 'bullmq'
import { Injectable, Logger } from '@nestjs/common'
import type { Queue } from 'bullmq'

import { HISTORY_QUEUE } from './constants'
import { InjectHistoryQueue } from './decorators'

import type { User } from '@modules/users'

type QueueEventsListeners = Partial<{
  [K in keyof IQueueEventsListener as `on${Capitalize<K>}`]: IQueueEventsListener[K]
}>

type QueueEventListenerParams<TListener extends keyof IQueueEventsListener> =
  Parameters<IQueueEventsListener[TListener]>[0]

@QueueEventsListener(HISTORY_QUEUE)
@Injectable()
export class HistoryQueueEvents
  extends QueueEventsHost
  implements QueueEventsListeners
{
  private readonly logger = new Logger(HistoryQueueEvents.name)

  constructor(
    @InjectHistoryQueue() private readonly historyQueue: Queue<User>
  ) {
    super()
  }

  @OnQueueEvent('error')
  onError(error: Error) {
    this.logger.error(error)
  }

  @OnQueueEvent('failed')
  async onFailed({ jobId, failedReason }: QueueEventListenerParams<'failed'>) {
    const job = await this.historyQueue.getJob(jobId)

    if (!job) return

    const {
      data: { profile },
    } = job

    this.logger.error(
      `History synchronization failed for user: ${profile.displayName}`
    )
    this.logger.error(failedReason)
  }

  @OnQueueEvent('active')
  async onActive({ jobId }: QueueEventListenerParams<'active'>) {
    const job = await this.historyQueue.getJob(jobId)

    if (!job) return

    const {
      data: { profile },
    } = job

    this.logger.log(
      `Processing history synchronization for user: ${profile.displayName}...`
    )
  }

  @OnQueueEvent('completed')
  async onCompleted({ jobId }: QueueEventListenerParams<'completed'>) {
    const job = await this.historyQueue.getJob(jobId)

    if (!job) return

    const {
      data: { profile },
    } = job

    this.logger.log(
      `History synchronization completed for user: ${profile.displayName}`
    )
  }

  @OnQueueEvent('stalled')
  async onStalled({ jobId }: QueueEventListenerParams<'stalled'>) {
    const job = await this.historyQueue.getJob(jobId)

    if (!job) return

    const {
      data: { profile },
    } = job

    this.logger.error(
      `History synchronization stalled for user: ${profile.displayName}`
    )
  }
}

Describe the solution you'd like

Maybe QueueEventsHost class should have this methods defined so inferring types won't be so hard.

Teachability, documentation, adoption, migration strategy

No response

What is the motivation / use case for changing the behavior?

Better type safety.

@Mnigos Mnigos added the feature label Jul 30, 2024
@doneumark
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants