Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/api/v2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.335",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@9.9.9",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

publish libraries before merge

"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
"@calcom/prisma": "*",
Expand Down
4 changes: 2 additions & 2 deletions apps/api/v2/src/lib/logger.bridge.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, Logger as NestLogger, Scope } from "@nestjs/common";
import { Logger as NestLogger } from "@nestjs/common";

// 1. Define an interface for the settings
interface IMyLoggerSettings {
Expand All @@ -22,7 +22,7 @@ const LogLevel = {
* from platform libraries. It forwards logs to NestLogger, allowing centralization
* (e.g., sending to Axiom) and adds an optional prefix for context.
*/
@Injectable({ scope: Scope.TRANSIENT }) // TRANSIENT ensures getSubLogger provides truly independent instances if needed elsewhere
// TODO: now that we have dependency injection, we need to correctly handle adding the request object to this logger using decorators on api v2
export class Logger {
// Use NestLogger for the actual logging output
private readonly nestLogger = new NestLogger("LoggerBridge");
Expand Down
12 changes: 12 additions & 0 deletions apps/api/v2/src/lib/modules/google-calendar-tasker.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Logger } from "@/lib/logger.bridge";
import { GoogleCalendarSyncTasker } from "@/lib/services/taskers/google-calendar-sync-tasker.service";
import { GoogleCalendarTasker } from "@/lib/services/taskers/google-calendar-tasker.service";
import { GoogleCalendarTriggerDevTasker } from "@/lib/services/taskers/google-calendar-trigger-tasker.service";
import { Module } from "@nestjs/common";

@Module({
imports: [],
providers: [GoogleCalendarSyncTasker, GoogleCalendarTriggerDevTasker, Logger, GoogleCalendarTasker],
exports: [GoogleCalendarTasker],
})
export class GoogleCalendarTaskerModule {}
Comment on lines +1 to +12
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

module which can be used within api v2 controller to inject google calendar tasker

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Logger } from "@/lib/logger.bridge";
import { Injectable } from "@nestjs/common";

import { GoogleCalendarSyncTasker as BaseGoogleCalendarSyncTasker } from "@calcom/platform-libraries/taskers";

@Injectable()
export class GoogleCalendarSyncTasker extends BaseGoogleCalendarSyncTasker {
constructor(logger: Logger) {
super({
logger,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Logger } from "@/lib/logger.bridge";
import { Injectable } from "@nestjs/common";

import { GoogleCalendarTasker as BaseGoogleCalendarTasker } from "@calcom/platform-libraries/taskers";

import { GoogleCalendarSyncTasker } from "./google-calendar-sync-tasker.service";
import { GoogleCalendarTriggerDevTasker } from "./google-calendar-trigger-tasker.service";

@Injectable()
export class GoogleCalendarTasker extends BaseGoogleCalendarTasker {
constructor(
primaryTasker: GoogleCalendarTriggerDevTasker,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for example here:

ApiV2 could provide it's own BullMQ tasker

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this could also be controller by env variable

fallbackTasker: GoogleCalendarSyncTasker,
logger: Logger
) {
super({
primaryTasker: primaryTasker,
fallbackTasker: fallbackTasker,
logger,
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Logger } from "@/lib/logger.bridge";
import { Injectable } from "@nestjs/common";

import { GoogleCalendarTriggerDevTasker as BaseGoogleCalendarTriggerDevTasker } from "@calcom/platform-libraries/taskers";

@Injectable()
export class GoogleCalendarTriggerDevTasker extends BaseGoogleCalendarTriggerDevTasker {
constructor(logger: Logger) {
super({
logger,
});
}
}
3 changes: 2 additions & 1 deletion apps/api/v2/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"@calcom/platform-libraries/conferencing": ["../../../packages/platform/libraries/conferencing.ts"],
"@calcom/platform-libraries/repositories": ["../../../packages/platform/libraries/repositories.ts"],
"@calcom/platform-libraries/bookings": ["../../../packages/platform/libraries/bookings.ts"],
"@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"]
"@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"],
"@calcom/platform-libraries/taskers": ["../../../packages/platform/libraries/taskers.ts"]
Comment on lines +31 to +32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Path alias overrides the package export; remove it to avoid split sources.

@calcom/platform-libraries now exports "taskers". Keeping this alias points imports to a raw TS file and can desync with the published package. Remove the alias and fix the dangling comma.

-      "@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"],
-      "@calcom/platform-libraries/taskers": ["../../../packages/platform/libraries/taskers.ts"]
+      "@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"],
"@calcom/platform-libraries/taskers": ["../../../packages/platform/libraries/taskers.ts"]
"@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"]
🤖 Prompt for AI Agents
In apps/api/v2/tsconfig.json around lines 31 to 32, the path alias for
"@calcom/platform-libraries/taskers" overrides the package export and points to
a raw TS file; remove the entire "@calcom/platform-libraries/taskers" alias
entry from the paths section so imports resolve to the packaged export instead,
and after removing the line ensure the JSON stays valid by deleting the
now-dangling trailing comma (or adjusting commas appropriately).

},
"incremental": true,
"skipLibCheck": true,
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@calcom/platform-enums": "*",
"@calcom/platform-types": "*",
"@calcom/prisma": "*",
"@calcom/trigger": "workspace:^",
"@calcom/trpc": "*",
"@calcom/tsconfig": "*",
"@calcom/ui": "*",
Expand Down
48 changes: 48 additions & 0 deletions packages/features/tasker/SafeDispatchTasker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// No need for a generic base 'TaskerInterface'. We will use the specific domain interface directly.
// For example, ICalendarTasker.
import type { ILogger } from "./types/logger";

export abstract class BaseTaskerService<T> {
// T is now just a placeholder for the class that extends this
// The dependencies are now typed with the specific interfaces
protected readonly primaryTasker: T;
protected readonly fallbackTasker: T;
protected readonly logger: ILogger;

constructor(dependencies: { primaryTasker: T; fallbackTasker: T; logger: ILogger }) {
this.primaryTasker = dependencies.primaryTasker;
this.fallbackTasker = dependencies.fallbackTasker;
this.logger = dependencies.logger;
}

public async dispatch<K extends keyof T>(
taskName: K,
...args: T[K] extends (...args: any[]) => any ? Parameters<T[K]> : never
): Promise<T[K] extends (...args: any[]) => any ? Awaited<ReturnType<T[K]>> : never> {
this.logger.info(`Dispatching task '${String(taskName)}'`, { args });
return this.safeDispatch(taskName, ...args);
}

// The dispatch method is now strongly typed to the keys of T
protected async safeDispatch<K extends keyof T>(
taskName: K,
// We infer the arguments directly from the method on T
...args: T[K] extends (...args: any[]) => any ? Parameters<T[K]> : never
): Promise<T[K] extends (...args: any[]) => any ? Awaited<ReturnType<T[K]>> : never> {
try {
const method = this.primaryTasker[taskName] as (...args: any[]) => any;
return await method.apply(this.primaryTasker, args);
} catch (err) {
this.logger.error(`Primary tasker failed for '${String(taskName)}'.`, err as Error);

if (this.primaryTasker === this.fallbackTasker) {
throw err;
}

this.logger.warn(`Falling back to SyncTasker for '${String(taskName)}'.`);

const fallbackMethod = this.fallbackTasker[taskName] as (...args: any[]) => any;
return fallbackMethod.apply(this.fallbackTasker, args);
}
}
}
Comment on lines +1 to +48
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the base tasker class which specialized taskers will extends, this ensures the fallback tasker is called if the primary tasker fails (for example is trigger.dev is down)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this also abstract the logic of dispatch and safeDispatch so that people implementing Specialized taskers do not have to worry with it

Loading
Loading