@financial-times/cp-content-pipeline-schema 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.2.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v2.1.0...cp-content-pipeline-schema-v2.2.0) (2024-02-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * explicitly log a 408 to graphite if request is aborted ([4da9d5a](https://github.com/Financial-Times/cp-content-pipeline/commit/4da9d5a427e36599bed9b1c879366029e395f76e))
9
+
3
10
  ## [2.1.0](https://github.com/Financial-Times/cp-content-pipeline/compare/cp-content-pipeline-schema-v2.0.3...cp-content-pipeline-schema-v2.1.0) (2024-02-28)
4
11
 
5
12
 
@@ -1,8 +1,7 @@
1
- import { WillSendRequestOptions } from '@apollo/datasource-rest';
2
1
  import { CapiResponse } from '../model/CapiResponse';
3
2
  import { InstrumentedRESTDataSource } from './instrumented';
4
3
  import { CapiPerson } from '../types/internal-content';
5
- import { CacheOptions } from '@apollo/datasource-rest/dist/RESTDataSource';
4
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest';
6
5
  export declare class CapiDataSource extends InstrumentedRESTDataSource {
7
6
  baseURL: string;
8
7
  capiKey: string;
@@ -12,7 +11,7 @@ export declare class CapiDataSource extends InstrumentedRESTDataSource {
12
11
  abortController: AbortController;
13
12
  timeout: ReturnType<typeof setTimeout> | undefined;
14
13
  nextNotificationLink?: string;
15
- willSendRequest(request: WillSendRequestOptions): void;
14
+ willSendRequest(path: string, request: AugmentedRequest): void;
16
15
  protected cacheOptionsFor(url: string): CacheOptions | undefined;
17
16
  getContent(uuid: string, packageContainer?: CapiResponse): Promise<CapiResponse>;
18
17
  getPerson(uuid: string): Promise<CapiPerson>;
@@ -20,8 +20,8 @@ class CapiDataSource extends instrumented_1.InstrumentedRESTDataSource {
20
20
  this.abortController = new AbortController();
21
21
  this.timeout = undefined;
22
22
  }
23
- willSendRequest(request) {
24
- super.willSendRequest(request);
23
+ willSendRequest(path, request) {
24
+ super.willSendRequest(path, request);
25
25
  request.headers['x-api-key'] = this.capiKey;
26
26
  request.signal = this.abortController.signal;
27
27
  this.timeout = setTimeout(() => this.abortController.abort(), REQUEST_TIMEOUT);
@@ -1 +1 @@
1
- {"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capi.js","sourceRoot":"","sources":["../../src/datasources/capi.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,4 @@
1
- import { WillSendRequestOptions, RESTDataSource, RequestOptions } from '@apollo/datasource-rest';
2
- import type { FetcherResponse } from '@apollo/utils.fetcher';
1
+ import { RESTDataSource, CacheOptions, DataSourceFetchResult, DataSourceRequest, AugmentedRequest } from '@apollo/datasource-rest';
3
2
  import { QueryContext } from '..';
4
3
  import { BaseDataSource, BaseDataSourceOptions } from './base';
5
4
  export declare class InstrumentedRESTDataSource extends RESTDataSource implements BaseDataSource {
@@ -8,7 +7,7 @@ export declare class InstrumentedRESTDataSource extends RESTDataSource implement
8
7
  context: QueryContext;
9
8
  constructor({ cache, context }: BaseDataSourceOptions);
10
9
  get cachePrefix(): string;
11
- willSendRequest(request: WillSendRequestOptions): void;
12
- trace<TResult>(url: URL, request: WillSendRequestOptions, fn: () => Promise<TResult>): Promise<TResult>;
13
- didReceiveResponse<TResult>(response: FetcherResponse, request: RequestOptions): Promise<TResult>;
10
+ willSendRequest(path: string, request: AugmentedRequest): void;
11
+ throwIfResponseIsError(): Promise<void>;
12
+ fetch<TResult>(path: string, incomingRequest?: DataSourceRequest<CacheOptions>): Promise<DataSourceFetchResult<TResult>>;
14
13
  }
@@ -22,44 +22,50 @@ class InstrumentedRESTDataSource extends datasource_rest_1.RESTDataSource {
22
22
  get cachePrefix() {
23
23
  return this.constructor.name.replace(/DataSource$/, '').toLowerCase();
24
24
  }
25
- willSendRequest(request) {
25
+ willSendRequest(path, request) {
26
26
  request.headers['user-agent'] = `cp-content-pipeline-api/${this.context.versions.api} cp-content-pipeline-schema/${this.context.versions.schema} `;
27
+ if (this.context.requestId && !this.context.contentRequestedOnce) {
28
+ request.headers['x-request-id'] = this.context.requestId;
29
+ }
27
30
  }
28
- async trace(url, request, fn) {
29
- this.startTime = process.hrtime.bigint();
31
+ // we implement our own error handling so skip the built-in GraphQLError
32
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
33
+ async throwIfResponseIsError() { }
34
+ async fetch(path, incomingRequest) {
35
+ const startTime = process.hrtime.bigint();
30
36
  this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.request.count`, 1);
31
37
  this.context.logger.info({
32
38
  event: 'REQUEST_DATASOURCE',
33
39
  datasource: this.constructor.name,
34
40
  request: {
35
41
  id: this.context.requestId,
36
- url: url.href,
37
- method: request.method,
42
+ url: new URL(path, this.baseURL).href,
43
+ method: incomingRequest?.method,
38
44
  },
39
45
  });
40
- if (this.context.requestId && !this.context.contentRequestedOnce) {
41
- request.headers['x-request-id'] = this.context.requestId;
42
- }
43
- return fn();
44
- }
45
- async didReceiveResponse(response, request) {
46
- // this.startTime will definitely have been set by willSendRequest, but no way of encoding that in types
47
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
48
- const duration = (process.hrtime.bigint() - this.startTime) / BigInt(1e6);
49
- this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.${response.status}.count`, 1);
50
- this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.${response.status}.time`, Number(duration));
51
- if (response.ok) {
52
- return super.didReceiveResponse(response, request);
46
+ try {
47
+ const result = await super.fetch(path, incomingRequest);
48
+ const duration = (process.hrtime.bigint() - startTime) / BigInt(1e6);
49
+ this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.${result.response.status}.count`, 1);
50
+ this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.${result.response.status}.time`, Number(duration));
51
+ if (!result.response.ok) {
52
+ throw new errors_1.UpstreamServiceError({
53
+ message: `${result.response.status}: ${result.response.statusText} from ${this.constructor.name}`,
54
+ statusCode: result.response.status,
55
+ relatesToSystems: this.backendSystemCodes,
56
+ url: result.response.url,
57
+ body: result.parsedBody,
58
+ });
59
+ }
60
+ return result;
53
61
  }
54
- else {
55
- const body = await this.parseBody(response);
56
- throw new errors_1.UpstreamServiceError({
57
- message: `${response.status}: ${response.statusText} from ${this.constructor.name}`,
58
- statusCode: response.status,
59
- relatesToSystems: this.backendSystemCodes,
60
- url: response.url,
61
- body,
62
- });
62
+ catch (error) {
63
+ if (error instanceof Error && error.name === 'AbortError') {
64
+ const duration = (process.hrtime.bigint() - startTime) / BigInt(1e6);
65
+ this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.408.count`, 1);
66
+ this.context.metrics?.count(`graphql.datasource.${this.constructor.name}.response.408.time`, Number(duration));
67
+ }
68
+ throw error;
63
69
  }
64
70
  }
65
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"instrumented.js","sourceRoot":"","sources":["../../src/datasources/instrumented.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"instrumented.js","sourceRoot":"","sources":["../../src/datasources/instrumented.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,12 @@
1
- import { WillSendRequestOptions } from '@apollo/datasource-rest';
2
1
  import { InstrumentedRESTDataSource } from './instrumented';
3
- import { CacheOptions } from '@apollo/datasource-rest/dist/RESTDataSource';
2
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest';
4
3
  export declare class OrigamiImageDataSource extends InstrumentedRESTDataSource {
5
4
  baseURL: string;
6
5
  backendSystemCodes: string[];
7
6
  abortController: AbortController;
8
7
  timeout: ReturnType<typeof setTimeout> | undefined;
9
8
  imageMetadataCacheTTL: number;
10
- willSendRequest(request: WillSendRequestOptions): void;
9
+ willSendRequest(path: string, request: AugmentedRequest): void;
11
10
  protected cacheOptionsFor(): CacheOptions;
12
11
  getImageMetadata(url: string): Promise<{
13
12
  width: number;
@@ -15,8 +15,8 @@ class OrigamiImageDataSource extends instrumented_1.InstrumentedRESTDataSource {
15
15
  ? parseInt(process.env.IMAGE_METADATA_CACHE_TTL)
16
16
  : 60 * 60 * 24 * 7; // 1 week
17
17
  }
18
- willSendRequest(request) {
19
- super.willSendRequest(request);
18
+ willSendRequest(path, request) {
19
+ super.willSendRequest(path, request);
20
20
  request.signal = this.abortController.signal;
21
21
  this.timeout = setTimeout(() => this.abortController.abort(), REQUEST_TIMEOUT);
22
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"origami-image.js","sourceRoot":"","sources":["../../src/datasources/origami-image.ts"],"names":[],"mappings":";;;AACA,2DAGuC;AACvC,iDAA2D;AAG3D,MAAM,eAAe,GAAG,IAAI,CAAA,CAAC,YAAY;AAEzC,MAAa,sBAAuB,SAAQ,yCAA0B;IAAtE;;QACE,YAAO,GAAG,+CAA+C,CAAA;QACzD,uBAAkB,GAAG,CAAC,0BAA0B,CAAC,CAAA;QAEjD,oBAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QACvC,YAAO,GAA8C,SAAS,CAAA;QAE9D,0BAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB;YAC1D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;YAChD,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,CAAC,SAAS;IAyChC,CAAC;IAvCU,eAAe,CAAC,OAA+B;QACtD,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;QAE9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAA;QAC5C,IAAI,CAAC,OAAO,GAAG,UAAU,CACvB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAClC,eAAe,CAChB,CAAA;IACH,CAAC;IAES,eAAe;QACvB,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,qBAAqB,EAAE,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,GAAW;QAEX,IAAI;YACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,GAAG,CAClC,oBAAoB,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAC1D,CAAA;YACD,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;aACzB;YACD,OAAO,aAAa,CAAA;SACrB;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE;gBACzD,MAAM,IAAI,6BAAoB,CAAC;oBAC7B,IAAI,EAAE,4BAA4B;oBAClC,OAAO,EAAE,6CAA6C,eAAe,8BAA8B;oBACnG,UAAU,EAAE,GAAG;oBACf,gBAAgB,EAAE,IAAI,CAAC,kBAAkB;iBAC1C,CAAC,CAAA;aACH;YAED,MAAM,KAAK,CAAA;SACZ;IACH,CAAC;CACF;AAlDD,wDAkDC"}
1
+ {"version":3,"file":"origami-image.js","sourceRoot":"","sources":["../../src/datasources/origami-image.ts"],"names":[],"mappings":";;;AAAA,2DAAqE;AACrE,iDAA2D;AAG3D,MAAM,eAAe,GAAG,IAAI,CAAA,CAAC,YAAY;AAEzC,MAAa,sBAAuB,SAAQ,yCAA0B;IAAtE;;QACE,YAAO,GAAG,+CAA+C,CAAA;QACzD,uBAAkB,GAAG,CAAC,0BAA0B,CAAC,CAAA;QAEjD,oBAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QACvC,YAAO,GAA8C,SAAS,CAAA;QAE9D,0BAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB;YAC1D,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;YAChD,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,CAAC,SAAS;IAyChC,CAAC;IAvCU,eAAe,CAAC,IAAY,EAAE,OAAyB;QAC9D,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAA;QAC5C,IAAI,CAAC,OAAO,GAAG,UAAU,CACvB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAClC,eAAe,CAChB,CAAA;IACH,CAAC;IAES,eAAe;QACvB,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,qBAAqB,EAAE,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,gBAAgB,CACpB,GAAW;QAEX,IAAI;YACF,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,GAAG,CAClC,oBAAoB,kBAAkB,CAAC,GAAG,CAAC,cAAc,CAC1D,CAAA;YACD,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;aACzB;YACD,OAAO,aAAa,CAAA;SACrB;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE;gBACzD,MAAM,IAAI,6BAAoB,CAAC;oBAC7B,IAAI,EAAE,4BAA4B;oBAClC,OAAO,EAAE,6CAA6C,eAAe,8BAA8B;oBACnG,UAAU,EAAE,GAAG;oBACf,gBAAgB,EAAE,IAAI,CAAC,kBAAkB;iBAC1C,CAAC,CAAA;aACH;YAED,MAAM,KAAK,CAAA;SACZ;IACH,CAAC;CACF;AAlDD,wDAkDC"}
@@ -1,11 +1,11 @@
1
- import { CacheOptions, WillSendRequestOptions } from '@apollo/datasource-rest/dist/RESTDataSource';
1
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest';
2
2
  import { InstrumentedRESTDataSource } from './instrumented';
3
3
  export declare class TwitterDataSource extends InstrumentedRESTDataSource {
4
4
  baseURL: string;
5
5
  backendSystemCodes: string[];
6
6
  abortController: AbortController;
7
7
  timeout: ReturnType<typeof setTimeout> | undefined;
8
- willSendRequest(request: WillSendRequestOptions): void;
8
+ willSendRequest(path: string, request: AugmentedRequest): void;
9
9
  getTweet(tweetUrl: string): Promise<any>;
10
10
  cacheOptionsFor(): CacheOptions;
11
11
  }
@@ -12,8 +12,8 @@ class TwitterDataSource extends instrumented_1.InstrumentedRESTDataSource {
12
12
  this.abortController = new AbortController();
13
13
  this.timeout = undefined;
14
14
  }
15
- willSendRequest(request) {
16
- super.willSendRequest(request);
15
+ willSendRequest(path, request) {
16
+ super.willSendRequest(path, request);
17
17
  request.signal = this.abortController.signal;
18
18
  this.timeout = setTimeout(() => this.abortController.abort(), REQUEST_TIMEOUT);
19
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"twitter.js","sourceRoot":"","sources":["../../src/datasources/twitter.ts"],"names":[],"mappings":";;;AAIA,2DAGuC;AACvC,iDAA2D;AAE3D,MAAM,eAAe,GAAG,IAAI,CAAA,CAAC,YAAY;AACzC,MAAa,iBAAkB,SAAQ,yCAA0B;IAAjE;;QACE,YAAO,GAAG,6BAA6B,CAAA;QACvC,uBAAkB,GAAG,CAAC,oBAAoB,CAAC,CAAA;QAE3C,oBAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QACvC,YAAO,GAA8C,SAAS,CAAA;IAyChE,CAAC;IAvCU,eAAe,CAAC,OAA+B;QACtD,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;QAE9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAA;QAC5C,IAAI,CAAC,OAAO,GAAG,UAAU,CACvB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAClC,eAAe,CAChB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,QAAQ,mBAAmB,CAAC,CAAA;YAExE,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;aACzB;YAED,OAAO,KAAK,CAAA;SACb;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE;gBACzD,MAAM,IAAI,6BAAoB,CAAC;oBAC7B,IAAI,EAAE,4BAA4B;oBAClC,OAAO,EAAE,2CAA2C,eAAe,8BAA8B;oBACjG,UAAU,EAAE,GAAG;oBACf,gBAAgB,EAAE,IAAI,CAAC,kBAAkB;iBAC1C,CAAC,CAAA;aACH;YAED,MAAM,KAAK,CAAA;SACZ;IACH,CAAC;IAED,eAAe;QACb,iFAAiF;QACjF,oFAAoF;QACpF,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;IACtB,CAAC;CACF;AA9CD,8CA8CC"}
1
+ {"version":3,"file":"twitter.js","sourceRoot":"","sources":["../../src/datasources/twitter.ts"],"names":[],"mappings":";;;AACA,2DAAqE;AACrE,iDAA2D;AAE3D,MAAM,eAAe,GAAG,IAAI,CAAA,CAAC,YAAY;AACzC,MAAa,iBAAkB,SAAQ,yCAA0B;IAAjE;;QACE,YAAO,GAAG,6BAA6B,CAAA;QACvC,uBAAkB,GAAG,CAAC,oBAAoB,CAAC,CAAA;QAE3C,oBAAe,GAAG,IAAI,eAAe,EAAE,CAAA;QACvC,YAAO,GAA8C,SAAS,CAAA;IAyChE,CAAC;IAvCU,eAAe,CAAC,IAAY,EAAE,OAAyB;QAC9D,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEpC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAA;QAC5C,IAAI,CAAC,OAAO,GAAG,UAAU,CACvB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,EAClC,eAAe,CAChB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,IAAI;YACF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,QAAQ,mBAAmB,CAAC,CAAA;YAExE,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;aACzB;YAED,OAAO,KAAK,CAAA;SACb;QAAC,OAAO,KAAK,EAAE;YACd,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE;gBACzD,MAAM,IAAI,6BAAoB,CAAC;oBAC7B,IAAI,EAAE,4BAA4B;oBAClC,OAAO,EAAE,2CAA2C,eAAe,8BAA8B;oBACjG,UAAU,EAAE,GAAG;oBACf,gBAAgB,EAAE,IAAI,CAAC,kBAAkB;iBAC1C,CAAC,CAAA;aACH;YAED,MAAM,KAAK,CAAA;SACZ;IACH,CAAC;IAED,eAAe;QACb,iFAAiF;QACjF,oFAAoF;QACpF,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;IACtB,CAAC;CACF;AA9CD,8CA8CC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/cp-content-pipeline-schema",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "homepage": "https://github.com/Financial-Times/cp-content-pipeline#readme",
20
20
  "dependencies": {
21
- "@apollo/datasource-rest": "^4.3.2",
21
+ "@apollo/datasource-rest": "^6.2.2",
22
22
  "@apollo/utils.keyvaluecache": "^1.0.1",
23
23
  "@dotcom-reliability-kit/errors": "^2.0.0",
24
24
  "@dotcom-reliability-kit/log-error": "^2.0.0",
@@ -1,13 +1,11 @@
1
- import { WillSendRequestOptions } from '@apollo/datasource-rest'
2
1
  import { CapiResponse } from '../model/CapiResponse'
3
2
  import { InstrumentedRESTDataSource } from './instrumented'
4
3
  import { CapiPerson } from '../types/internal-content'
5
- import { CacheOptions } from '@apollo/datasource-rest/dist/RESTDataSource'
4
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest'
6
5
  import {
7
6
  OperationalError,
8
7
  UpstreamServiceError,
9
8
  } from '@dotcom-reliability-kit/errors'
10
- import { uuidFromUrl } from '../helpers/metadata'
11
9
 
12
10
  const REQUEST_TIMEOUT = 5000 // 5 seconds
13
11
 
@@ -28,8 +26,8 @@ export class CapiDataSource extends InstrumentedRESTDataSource {
28
26
 
29
27
  nextNotificationLink?: string
30
28
 
31
- override willSendRequest(request: WillSendRequestOptions) {
32
- super.willSendRequest(request)
29
+ override willSendRequest(path: string, request: AugmentedRequest) {
30
+ super.willSendRequest(path, request)
33
31
 
34
32
  request.headers['x-api-key'] = this.capiKey
35
33
  request.signal = this.abortController.signal
@@ -1,9 +1,10 @@
1
1
  import {
2
- WillSendRequestOptions,
3
2
  RESTDataSource,
4
- RequestOptions,
3
+ CacheOptions,
4
+ DataSourceFetchResult,
5
+ DataSourceRequest,
6
+ AugmentedRequest,
5
7
  } from '@apollo/datasource-rest'
6
- import type { FetcherResponse } from '@apollo/utils.fetcher'
7
8
  import { PrefixingKeyValueCache } from '@apollo/utils.keyvaluecache'
8
9
  import { SerializedRequest } from '@dotcom-reliability-kit/serialize-request'
9
10
  import { UpstreamServiceError } from '@dotcom-reliability-kit/errors'
@@ -40,69 +41,82 @@ export class InstrumentedRESTDataSource
40
41
  return this.constructor.name.replace(/DataSource$/, '').toLowerCase()
41
42
  }
42
43
 
43
- override willSendRequest(request: WillSendRequestOptions): void {
44
+ override willSendRequest(path: string, request: AugmentedRequest): void {
44
45
  request.headers[
45
46
  'user-agent'
46
47
  ] = `cp-content-pipeline-api/${this.context.versions.api} cp-content-pipeline-schema/${this.context.versions.schema} `
48
+
49
+ if (this.context.requestId && !this.context.contentRequestedOnce) {
50
+ request.headers['x-request-id'] = this.context.requestId
51
+ }
47
52
  }
48
53
 
49
- override async trace<TResult>(
50
- url: URL,
51
- request: WillSendRequestOptions,
52
- fn: () => Promise<TResult>
53
- ): Promise<TResult> {
54
- this.startTime = process.hrtime.bigint()
54
+ // we implement our own error handling so skip the built-in GraphQLError
55
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
56
+ async throwIfResponseIsError() {}
57
+
58
+ async fetch<TResult>(
59
+ path: string,
60
+ incomingRequest?: DataSourceRequest<CacheOptions>
61
+ ): Promise<DataSourceFetchResult<TResult>> {
62
+ const startTime = process.hrtime.bigint()
55
63
 
56
64
  this.context.metrics?.count(
57
65
  `graphql.datasource.${this.constructor.name}.request.count`,
58
66
  1
59
67
  )
68
+
60
69
  this.context.logger.info({
61
70
  event: 'REQUEST_DATASOURCE',
62
71
  datasource: this.constructor.name,
63
72
  request: {
64
73
  id: this.context.requestId,
65
- url: url.href,
66
- method: request.method,
74
+ url: new URL(path, this.baseURL).href,
75
+ method: incomingRequest?.method,
67
76
  } as SerializedRequest,
68
77
  })
69
78
 
70
- if (this.context.requestId && !this.context.contentRequestedOnce) {
71
- request.headers['x-request-id'] = this.context.requestId
72
- }
79
+ try {
80
+ const result = await super.fetch<TResult>(path, incomingRequest)
81
+ const duration = (process.hrtime.bigint() - startTime) / BigInt(1e6)
73
82
 
74
- return fn()
75
- }
83
+ this.context.metrics?.count(
84
+ `graphql.datasource.${this.constructor.name}.response.${result.response.status}.count`,
85
+ 1
86
+ )
76
87
 
77
- async didReceiveResponse<TResult>(
78
- response: FetcherResponse,
79
- request: RequestOptions
80
- ): Promise<TResult> {
81
- // this.startTime will definitely have been set by willSendRequest, but no way of encoding that in types
82
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
83
- const duration = (process.hrtime.bigint() - this.startTime!) / BigInt(1e6)
88
+ this.context.metrics?.count(
89
+ `graphql.datasource.${this.constructor.name}.response.${result.response.status}.time`,
90
+ Number(duration)
91
+ )
84
92
 
85
- this.context.metrics?.count(
86
- `graphql.datasource.${this.constructor.name}.response.${response.status}.count`,
87
- 1
88
- )
89
- this.context.metrics?.count(
90
- `graphql.datasource.${this.constructor.name}.response.${response.status}.time`,
91
- Number(duration)
92
- )
93
+ if (!result.response.ok) {
94
+ throw new UpstreamServiceError({
95
+ message: `${result.response.status}: ${result.response.statusText} from ${this.constructor.name}`,
96
+ statusCode: result.response.status,
97
+ relatesToSystems: this.backendSystemCodes,
98
+ url: result.response.url,
99
+ body: result.parsedBody,
100
+ })
101
+ }
102
+
103
+ return result
104
+ } catch (error) {
105
+ if (error instanceof Error && error.name === 'AbortError') {
106
+ const duration = (process.hrtime.bigint() - startTime) / BigInt(1e6)
107
+
108
+ this.context.metrics?.count(
109
+ `graphql.datasource.${this.constructor.name}.response.408.count`,
110
+ 1
111
+ )
112
+
113
+ this.context.metrics?.count(
114
+ `graphql.datasource.${this.constructor.name}.response.408.time`,
115
+ Number(duration)
116
+ )
117
+ }
93
118
 
94
- if (response.ok) {
95
- return super.didReceiveResponse(response, request)
96
- } else {
97
- const body = await this.parseBody(response)
98
-
99
- throw new UpstreamServiceError({
100
- message: `${response.status}: ${response.statusText} from ${this.constructor.name}`,
101
- statusCode: response.status,
102
- relatesToSystems: this.backendSystemCodes,
103
- url: response.url,
104
- body,
105
- })
119
+ throw error
106
120
  }
107
121
  }
108
122
  }
@@ -1,10 +1,6 @@
1
- import { WillSendRequestOptions } from '@apollo/datasource-rest'
2
- import {
3
- OperationalError,
4
- UpstreamServiceError,
5
- } from '@dotcom-reliability-kit/errors'
1
+ import { UpstreamServiceError } from '@dotcom-reliability-kit/errors'
6
2
  import { InstrumentedRESTDataSource } from './instrumented'
7
- import { CacheOptions } from '@apollo/datasource-rest/dist/RESTDataSource'
3
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest'
8
4
 
9
5
  const REQUEST_TIMEOUT = 5000 // 5 seconds
10
6
 
@@ -19,8 +15,8 @@ export class OrigamiImageDataSource extends InstrumentedRESTDataSource {
19
15
  ? parseInt(process.env.IMAGE_METADATA_CACHE_TTL)
20
16
  : 60 * 60 * 24 * 7 // 1 week
21
17
 
22
- override willSendRequest(request: WillSendRequestOptions) {
23
- super.willSendRequest(request)
18
+ override willSendRequest(path: string, request: AugmentedRequest) {
19
+ super.willSendRequest(path, request)
24
20
 
25
21
  request.signal = this.abortController.signal
26
22
  this.timeout = setTimeout(
@@ -1,11 +1,5 @@
1
- import {
2
- CacheOptions,
3
- WillSendRequestOptions,
4
- } from '@apollo/datasource-rest/dist/RESTDataSource'
5
- import {
6
- OperationalError,
7
- UpstreamServiceError,
8
- } from '@dotcom-reliability-kit/errors'
1
+ import { AugmentedRequest, CacheOptions } from '@apollo/datasource-rest'
2
+ import { UpstreamServiceError } from '@dotcom-reliability-kit/errors'
9
3
  import { InstrumentedRESTDataSource } from './instrumented'
10
4
 
11
5
  const REQUEST_TIMEOUT = 5000 // 5 seconds
@@ -16,8 +10,8 @@ export class TwitterDataSource extends InstrumentedRESTDataSource {
16
10
  abortController = new AbortController()
17
11
  timeout: ReturnType<typeof setTimeout> | undefined = undefined
18
12
 
19
- override willSendRequest(request: WillSendRequestOptions) {
20
- super.willSendRequest(request)
13
+ override willSendRequest(path: string, request: AugmentedRequest) {
14
+ super.willSendRequest(path, request)
21
15
 
22
16
  request.signal = this.abortController.signal
23
17
  this.timeout = setTimeout(