@@ -21,7 +21,14 @@ import {
2121 unflattenAttributes ,
2222} from "@trigger.dev/core/v3" ;
2323import { parseTraceparent , serializeTraceparent } from "@trigger.dev/core/v3/isomorphic" ;
24- import { Prisma , TaskEvent , TaskEventKind , TaskEventStatus } from "@trigger.dev/database" ;
24+ import {
25+ Prisma ,
26+ RuntimeEnvironmentType ,
27+ TaskEvent ,
28+ TaskEventKind ,
29+ TaskEventStatus ,
30+ TaskRun ,
31+ } from "@trigger.dev/database" ;
2532import { nanoid } from "nanoid" ;
2633import { createHash } from "node:crypto" ;
2734import { EventEmitter } from "node:stream" ;
@@ -350,18 +357,44 @@ export class EventRepository {
350357 return completedEvent ;
351358 }
352359
353- async cancelEvent ( event : TaskEventRecord , cancelledAt : Date , reason : string ) {
354- if ( ! event . isPartial ) {
355- return ;
356- }
360+ async cancelRunEvent ( {
361+ reason,
362+ run,
363+ cancelledAt,
364+ projectRef,
365+ environmentType,
366+ organizationId,
367+ } : {
368+ reason : string ;
369+ run : TaskRun ;
370+ cancelledAt : Date ;
371+ projectRef : string ;
372+ organizationId : string ;
373+ environmentType : RuntimeEnvironmentType ;
374+ } ) {
375+ const startTime = convertDateToNanoseconds ( run . createdAt ) ;
357376
358377 await this . insertImmediate ( {
359- ...omit ( event , "id" ) ,
378+ message : run . taskIdentifier ,
379+ serviceName : "api server" ,
380+ serviceNamespace : "trigger.dev" ,
381+ level : "TRACE" ,
382+ kind : "SERVER" ,
383+ traceId : run . traceId ,
384+ spanId : run . spanId ,
385+ parentId : run . parentSpanId ,
386+ runId : run . id ,
387+ taskSlug : run . taskIdentifier ,
388+ projectRef,
389+ projectId : run . projectId ,
390+ environmentId : run . runtimeEnvironmentId ,
391+ environmentType,
392+ organizationId,
360393 isPartial : false ,
361- isError : false ,
394+ isError : true ,
362395 isCancelled : true ,
363396 status : "ERROR" ,
364- links : event . links ?? [ ] ,
397+ runIsTest : run . isTest ,
365398 events : [
366399 {
367400 name : "cancellation" ,
@@ -370,56 +403,18 @@ export class EventRepository {
370403 reason,
371404 } ,
372405 } ,
373- ...( ( event . events as any [ ] ) ?? [ ] ) ,
374406 ] ,
375- duration : calculateDurationFromStart ( event . startTime , cancelledAt ) ,
376- properties : event . properties as Attributes ,
377- metadata : event . metadata as Attributes ,
378- style : event . style as Attributes ,
379- output : event . output as Attributes ,
380- outputType : event . outputType ,
381- payload : event . payload as Attributes ,
382- payloadType : event . payloadType ,
407+ startTime,
408+ properties : { } ,
409+ metadata : undefined ,
410+ style : undefined ,
411+ duration : calculateDurationFromStart ( startTime , cancelledAt ) ,
412+ output : undefined ,
413+ payload : undefined ,
414+ payloadType : undefined ,
383415 } ) ;
384416 }
385417
386- async cancelEvents ( events : TaskEventRecord [ ] , cancelledAt : Date , reason : string ) {
387- const eventsToCancel = events . filter ( ( event ) => event . isPartial ) ;
388-
389- if ( eventsToCancel . length === 0 ) {
390- return ;
391- }
392-
393- await this . insertMany (
394- eventsToCancel . map ( ( event ) => ( {
395- ...omit ( event , "id" ) ,
396- isPartial : false ,
397- isError : false ,
398- isCancelled : true ,
399- status : "ERROR" ,
400- links : event . links ?? [ ] ,
401- events : [
402- {
403- name : "cancellation" ,
404- time : cancelledAt ,
405- properties : {
406- reason,
407- } ,
408- } ,
409- ...( ( event . events as any [ ] ) ?? [ ] ) ,
410- ] ,
411- duration : calculateDurationFromStart ( event . startTime , cancelledAt ) ,
412- properties : event . properties as Attributes ,
413- metadata : event . metadata as Attributes ,
414- style : event . style as Attributes ,
415- output : event . output as Attributes ,
416- outputType : event . outputType ,
417- payload : event . payload as Attributes ,
418- payloadType : event . payloadType ,
419- } ) )
420- ) ;
421- }
422-
423418 async crashEvent ( {
424419 event,
425420 crashedAt,
@@ -567,7 +562,19 @@ export class EventRepository {
567562 }
568563
569564 if ( event . isCancelled || ! event . isPartial ) {
570- eventsBySpanId . set ( event . spanId , event ) ;
565+ // If we have a cancelled event and an existing partial event,
566+ // merge them: use cancelled event data but preserve style from the partial event
567+ if ( event . isCancelled && existingEvent . isPartial && ! existingEvent . isCancelled ) {
568+ const mergedEvent : PreparedEvent = {
569+ ...event , // Use cancelled event as base (has correct timing, status, events)
570+ // Preserve style from the original partial event
571+ style : existingEvent . style ,
572+ } ;
573+ eventsBySpanId . set ( event . spanId , mergedEvent ) ;
574+ } else {
575+ // For non-cancelled events or other cases, use the standard replacement logic
576+ eventsBySpanId . set ( event . spanId , event ) ;
577+ }
571578 }
572579 }
573580
@@ -583,6 +590,9 @@ export class EventRepository {
583590 event . duration
584591 ) ;
585592
593+ const isCancelled =
594+ event . isCancelled === true ? true : event . isPartial && ancestorCancelled ;
595+
586596 const span = {
587597 id : event . spanId ,
588598 parentId : event . parentId ?? undefined ,
@@ -592,9 +602,9 @@ export class EventRepository {
592602 message : event . message ,
593603 style : event . style ,
594604 duration,
595- isError : event . isError ,
605+ isError : isCancelled ? false : event . isError ,
596606 isPartial : ancestorCancelled ? false : event . isPartial ,
597- isCancelled : event . isCancelled === true ? true : event . isPartial && ancestorCancelled ,
607+ isCancelled,
598608 isDebug : event . kind === TaskEventKind . LOG ,
599609 startTime : getDateFromNanoseconds ( event . startTime ) ,
600610 level : event . level ,
@@ -618,6 +628,8 @@ export class EventRepository {
618628 return ;
619629 }
620630
631+ logger . debug ( "[getTraceSummary] result" , { rootSpan, spans } ) ;
632+
621633 return {
622634 rootSpan,
623635 spans,
@@ -1141,11 +1153,6 @@ export class EventRepository {
11411153 ) : Promise < TResult > {
11421154 const propagatedContext = extractContextFromCarrier ( options . context ?? { } ) ;
11431155
1144- logger . debug ( "[otelContext]" , {
1145- propagatedContext,
1146- options,
1147- } ) ;
1148-
11491156 const start = process . hrtime . bigint ( ) ;
11501157 const startTime = options . startTime ?? getNowInNanoseconds ( ) ;
11511158
@@ -1895,6 +1902,10 @@ export function getDateFromNanoseconds(nanoseconds: bigint) {
18951902 return new Date ( Number ( nanoseconds ) / 1_000_000 ) ;
18961903}
18971904
1905+ function convertDateToNanoseconds ( date : Date ) {
1906+ return BigInt ( date . getTime ( ) ) * BigInt ( 1_000_000 ) ;
1907+ }
1908+
18981909function nanosecondsToMilliseconds ( nanoseconds : bigint | number ) : number {
18991910 return Number ( nanoseconds ) / 1_000_000 ;
19001911}
0 commit comments