@@ -4,13 +4,17 @@ import {
4
4
readableStreamFromIterable ,
5
5
SubProcess ,
6
6
type SubprocessErrorData ,
7
+ trace ,
8
+ context ,
9
+ Context ,
7
10
} from "../../deps.ts" ;
8
- import { getTraceContext } from "../../gcp-tracing.ts" ;
9
11
10
12
import { templateHtml , makeErrorResponse , HtmlHeaders } from '../../lib/request-handling.ts' ;
11
13
import { findModuleSlug , resolveModuleUrl } from "../../lib/resolve.ts" ;
12
14
import { computeGraph , renderGraph } from "./compute.ts" ;
13
15
16
+ const tracer = trace . getTracer ( 'dependencies-of-api' ) ;
17
+
14
18
export async function * handleRequest ( req : Request , modSlug : string , args : URLSearchParams ) {
15
19
if ( modSlug == '' ) {
16
20
const url = args . get ( 'url' ) ;
@@ -78,20 +82,15 @@ const hideLoadMsg = `<style type="text/css">#graph-waiting { display: none; }</s
78
82
79
83
async function serveHtmlGraphPage ( req : Request , modUrl : string , modSlug : string , args : URLSearchParams ) {
80
84
args . set ( 'font' , 'Archivo Narrow' ) ;
81
- const ctx = getTraceContext ( ) ! ;
82
85
83
86
// Render the basic page first, so we can error more cleanly if that fails
84
87
let pageHtml = '' ;
85
88
try {
86
- pageHtml = await ctx . enterSpan ( {
87
- spanKind : 'INTERNAL' ,
88
- displayName : { value : 'Render page HTML' } ,
89
- startTime : new Date ( ) . toISOString ( ) ,
90
- } , ( ) => templateHtml ( 'feat/dependencies-of/public.html' , {
89
+ pageHtml = await templateHtml ( 'feat/dependencies-of/public.html' , {
91
90
module_slug : entities . encode ( modSlug ) ,
92
91
module_url : entities . encode ( modUrl ) ,
93
92
export_prefix : entities . encode ( `${ req . url } ${ req . url . includes ( '?' ) ? '&' : '?' } format=` ) ,
94
- } ) ) ;
93
+ } ) ;
95
94
} catch ( err ) {
96
95
return makeErrorResponse ( err ) ;
97
96
}
@@ -149,28 +148,44 @@ async function serveHtmlGraphPage(req: Request, modUrl: string, modSlug: string,
149
148
} ) ;
150
149
151
150
// Return the body in two parts, with a comment in between
152
- return new Response ( readableStreamFromIterable ( ( async function * ( ) {
151
+
152
+ async function * bodyGenerator ( ) {
153
153
try {
154
154
const encoder = new TextEncoder ( ) ;
155
155
yield encoder . encode ( pageHtml ) ;
156
156
157
157
yield encoder . encode ( "\n<!-- now waiting for graph ... " ) ;
158
158
const d0 = Date . now ( ) ;
159
- const graphText = await ctx . enterSpan ( {
160
- spanKind : "INTERNAL" ,
161
- startTime : new Date ( ) . toISOString ( ) ,
162
- displayName : { value : "Wait for graph text" } ,
163
- } , async ( ) => hideLoadMsg + await graphPromise ) ;
159
+ const span = tracer . startSpan ( 'Wait for graph text' ) ;
160
+ const graphText = hideLoadMsg + await graphPromise . finally ( ( ) => span . end ( ) ) ;
164
161
const millis = Date . now ( ) - d0 ;
165
162
yield encoder . encode ( `completed in ${ millis } ms -->\n\n` ) ;
166
163
167
164
yield encoder . encode ( graphText ) ;
168
-
169
- ctx . spans [ 0 ] . endTime = new Date ( ) . toISOString ( ) ; // TODO: ugh
170
165
} catch ( err ) {
171
166
console . error ( err )
172
167
}
173
- } ( ) ) ) , {
168
+ }
169
+
170
+ const bodyIterable = asyncGeneratorWithContext ( context . active ( ) , bodyGenerator ) ;
171
+ return new Response ( readableStreamFromIterable ( bodyIterable ) , {
174
172
headers : HtmlHeaders ,
175
173
} ) ;
176
174
}
175
+
176
+ async function * asyncGeneratorWithContext < T , TReturn , TNext > (
177
+ operationContext : Context ,
178
+ operation : ( ) => AsyncGenerator < T , TReturn , TNext > ,
179
+ ) : AsyncGenerator < T , TReturn , TNext > {
180
+ const generator = context . with ( operationContext , operation )
181
+ const next = context . bind ( operationContext , generator . next . bind ( generator ) )
182
+
183
+ let result : IteratorResult < T , TReturn > = await next ( )
184
+
185
+ while ( ! result . done ) {
186
+ const nextParam = yield result . value
187
+ result = await next ( nextParam )
188
+ }
189
+
190
+ return result . value
191
+ }
0 commit comments