mirror of
https://github.com/graphql-hive/console
synced 2026-05-23 17:18:23 +00:00
Dispose hive client on signal termination for yoga and envelop (#4109)
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
This commit is contained in:
parent
89f3d0c56d
commit
441b71fdab
6 changed files with 57 additions and 6 deletions
5
.changeset/long-frogs-deliver.md
Normal file
5
.changeset/long-frogs-deliver.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@graphql-hive/client": minor
|
||||
---
|
||||
|
||||
Automatic disposal of managed clients for Yoga and Envelop plugins.
|
||||
|
|
@ -2,7 +2,7 @@ import { createHash } from 'crypto';
|
|||
import axios from 'axios';
|
||||
import type { DocumentNode } from 'graphql';
|
||||
import type { ApolloServerPlugin } from '@apollo/server';
|
||||
import { createHive } from './client.js';
|
||||
import { autoDisposeSymbol, createHive } from './client.js';
|
||||
import type {
|
||||
HiveClient,
|
||||
HivePluginOptions,
|
||||
|
|
@ -263,7 +263,9 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
|
|||
if (isLegacyV0) {
|
||||
return {
|
||||
async serverWillStop() {
|
||||
await hive.dispose();
|
||||
if (hive[autoDisposeSymbol]) {
|
||||
await hive.dispose();
|
||||
}
|
||||
},
|
||||
} as any;
|
||||
}
|
||||
|
|
@ -272,7 +274,9 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
|
|||
|
||||
return Promise.resolve({
|
||||
async serverWillStop() {
|
||||
await hive.dispose();
|
||||
if (hive[autoDisposeSymbol]) {
|
||||
await hive.dispose();
|
||||
}
|
||||
},
|
||||
schemaDidLoadOrUpdate(schemaContext) {
|
||||
if (ctx.schema !== schemaContext.apiSchema) {
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ export function createHive(options: HivePluginOptions): HiveClient {
|
|||
|
||||
return {
|
||||
[hiveClientSymbol]: true,
|
||||
[autoDisposeSymbol]: options.autoDispose ?? true,
|
||||
info,
|
||||
reportSchema,
|
||||
collectUsage,
|
||||
|
|
@ -177,6 +178,7 @@ export function createHive(options: HivePluginOptions): HiveClient {
|
|||
}
|
||||
|
||||
export const hiveClientSymbol: unique symbol = Symbol('hive-client');
|
||||
export const autoDisposeSymbol: unique symbol = Symbol('hive-auto-dispose');
|
||||
|
||||
function createPrinter(values: string[]) {
|
||||
const maxLen = Math.max(...values.map(v => v.length)) + 4;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { Plugin } from '@envelop/types';
|
||||
import { createHive } from './client.js';
|
||||
import { autoDisposeSymbol, createHive } from './client.js';
|
||||
import type { HiveClient, HivePluginOptions } from './internal/types.js';
|
||||
import { isHiveClient } from './internal/utils.js';
|
||||
|
||||
|
|
@ -18,6 +18,22 @@ export function useHive(clientOrOptions: HiveClient | HivePluginOptions): Plugin
|
|||
|
||||
void hive.info();
|
||||
|
||||
if (hive[autoDisposeSymbol]) {
|
||||
if (global.process) {
|
||||
const signals = Array.isArray(hive[autoDisposeSymbol])
|
||||
? hive[autoDisposeSymbol]
|
||||
: ['SIGINT', 'SIGTERM'];
|
||||
for (const signal of signals) {
|
||||
process.once(signal, () => hive.dispose());
|
||||
}
|
||||
} else {
|
||||
console.error(
|
||||
'It seems that GraphQL Hive is not being executed in Node.js. ' +
|
||||
'Please attempt manual client disposal and use autoDispose: false option.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
onSchemaChange({ schema }) {
|
||||
hive.reportSchema({ schema });
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import type { ExecutionArgs } from 'graphql';
|
||||
import type { hiveClientSymbol } from '../client.js';
|
||||
import type { autoDisposeSymbol, hiveClientSymbol } from '../client.js';
|
||||
import type { AgentOptions } from './agent.js';
|
||||
import type { SchemaReporter } from './reporting.js';
|
||||
|
||||
export interface HiveClient {
|
||||
[hiveClientSymbol]: true;
|
||||
[autoDisposeSymbol]: boolean | NodeJS.Signals[];
|
||||
info(): Promise<void>;
|
||||
reportSchema: SchemaReporter['report'];
|
||||
collectUsage(): CollectUsageCallback;
|
||||
|
|
@ -189,6 +190,13 @@ export type HivePluginOptions = OptionalWhenFalse<
|
|||
* Disabled by default
|
||||
*/
|
||||
reporting?: HiveReportingPluginOptions | false;
|
||||
/**
|
||||
* Automatically dispose the client when the process is terminated
|
||||
*
|
||||
* Apollo: Enabled by default
|
||||
* Yoga / Envelop: Enabled by default for SIGINT and SIGTERM signals
|
||||
*/
|
||||
autoDispose?: boolean | NodeJS.Signals[];
|
||||
},
|
||||
'enabled',
|
||||
'token'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { DocumentNode, ExecutionArgs, GraphQLSchema, Kind, parse } from 'graphql';
|
||||
import type { GraphQLParams, Plugin } from 'graphql-yoga';
|
||||
import LRU from 'tiny-lru';
|
||||
import { createHive } from './client.js';
|
||||
import { autoDisposeSymbol, createHive } from './client.js';
|
||||
import type { CollectUsageCallback, HiveClient, HivePluginOptions } from './internal/types.js';
|
||||
import { isHiveClient } from './internal/utils.js';
|
||||
|
||||
|
|
@ -27,6 +27,22 @@ export function useHive(clientOrOptions: HiveClient | HivePluginOptions): Plugin
|
|||
|
||||
void hive.info();
|
||||
|
||||
if (hive[autoDisposeSymbol]) {
|
||||
if (global.process) {
|
||||
const signals = Array.isArray(hive[autoDisposeSymbol])
|
||||
? hive[autoDisposeSymbol]
|
||||
: ['SIGINT', 'SIGTERM'];
|
||||
for (const signal of signals) {
|
||||
process.once(signal, () => hive.dispose());
|
||||
}
|
||||
} else {
|
||||
console.error(
|
||||
'It seems that GraphQL Hive is not being executed in Node.js. ' +
|
||||
'Please attempt manual client disposal and use autoDispose: false option.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const parsedDocumentCache = LRU<DocumentNode>(10_000);
|
||||
let latestSchema: GraphQLSchema | null = null;
|
||||
const cache = new WeakMap<Request, CacheRecord>();
|
||||
|
|
|
|||
Loading…
Reference in a new issue