fix(CQ-API-3): Make activity logging fire-and-forget

Activity logging now catches and logs errors without propagating them.
This ensures activity logging failures never break primary operations.

Updated return type to ActivityLog | null to indicate potential failure.

Refs #339

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-05 19:26:34 -06:00
parent 722b16a903
commit 7e9022bf9b

View File

@@ -18,16 +18,25 @@ export class ActivityService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
/** /**
* Create a new activity log entry * Create a new activity log entry (fire-and-forget)
*
* Activity logging failures are logged but never propagate to callers.
* This ensures activity logging never breaks primary operations.
*
* @returns The created ActivityLog or null if logging failed
*/ */
async logActivity(input: CreateActivityLogInput): Promise<ActivityLog> { async logActivity(input: CreateActivityLogInput): Promise<ActivityLog | null> {
try { try {
return await this.prisma.activityLog.create({ return await this.prisma.activityLog.create({
data: input as unknown as Prisma.ActivityLogCreateInput, data: input as unknown as Prisma.ActivityLogCreateInput,
}); });
} catch (error) { } catch (error) {
this.logger.error("Failed to log activity", error); // Log the error but don't propagate - activity logging is fire-and-forget
throw error; this.logger.error(
`Failed to log activity: action=${input.action} entityType=${input.entityType} entityId=${input.entityId}`,
error instanceof Error ? error.stack : String(error)
);
return null;
} }
} }
@@ -167,7 +176,7 @@ export class ActivityService {
userId: string, userId: string,
taskId: string, taskId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -186,7 +195,7 @@ export class ActivityService {
userId: string, userId: string,
taskId: string, taskId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -205,7 +214,7 @@ export class ActivityService {
userId: string, userId: string,
taskId: string, taskId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -224,7 +233,7 @@ export class ActivityService {
userId: string, userId: string,
taskId: string, taskId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -243,7 +252,7 @@ export class ActivityService {
userId: string, userId: string,
taskId: string, taskId: string,
assigneeId: string assigneeId: string
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -262,7 +271,7 @@ export class ActivityService {
userId: string, userId: string,
eventId: string, eventId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -281,7 +290,7 @@ export class ActivityService {
userId: string, userId: string,
eventId: string, eventId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -300,7 +309,7 @@ export class ActivityService {
userId: string, userId: string,
eventId: string, eventId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -319,7 +328,7 @@ export class ActivityService {
userId: string, userId: string,
projectId: string, projectId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -338,7 +347,7 @@ export class ActivityService {
userId: string, userId: string,
projectId: string, projectId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -357,7 +366,7 @@ export class ActivityService {
userId: string, userId: string,
projectId: string, projectId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -375,7 +384,7 @@ export class ActivityService {
workspaceId: string, workspaceId: string,
userId: string, userId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -393,7 +402,7 @@ export class ActivityService {
workspaceId: string, workspaceId: string,
userId: string, userId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -412,7 +421,7 @@ export class ActivityService {
userId: string, userId: string,
memberId: string, memberId: string,
role: string role: string
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -430,7 +439,7 @@ export class ActivityService {
workspaceId: string, workspaceId: string,
userId: string, userId: string,
memberId: string memberId: string
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -448,7 +457,7 @@ export class ActivityService {
workspaceId: string, workspaceId: string,
userId: string, userId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -467,7 +476,7 @@ export class ActivityService {
userId: string, userId: string,
domainId: string, domainId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -486,7 +495,7 @@ export class ActivityService {
userId: string, userId: string,
domainId: string, domainId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -505,7 +514,7 @@ export class ActivityService {
userId: string, userId: string,
domainId: string, domainId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -524,7 +533,7 @@ export class ActivityService {
userId: string, userId: string,
ideaId: string, ideaId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -543,7 +552,7 @@ export class ActivityService {
userId: string, userId: string,
ideaId: string, ideaId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,
@@ -562,7 +571,7 @@ export class ActivityService {
userId: string, userId: string,
ideaId: string, ideaId: string,
details?: Prisma.JsonValue details?: Prisma.JsonValue
): Promise<ActivityLog> { ): Promise<ActivityLog | null> {
return this.logActivity({ return this.logActivity({
workspaceId, workspaceId,
userId, userId,