SnowLuma v2.4.2 source snapshot
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run

This commit is contained in:
TanTan committed 2026-11-13 09:02:00 +08:00
commit fa9c73363d
1367 files changed
+355735

No files matched your search

+155
View File
@@ -0,0 +1,155 @@
import { PassThrough } from 'node:stream';
import { Server } from '@modelcontextprotocol/server';
import { serveStdio, StdioServerTransport } from '@modelcontextprotocol/server/stdio';
import { afterEach, describe, expect, it, vi } from 'vitest';
import { shutdownRuntime } from '../src/shutdown';
afterEach(() => vi.restoreAllMocks());
describe('runtime shutdown', () => {
it('finishes durable cleanup before closing the protocol normally', async () => {
const durable = Promise.withResolvers<void>();
const closeProtocol = vi.fn(async () => undefined);
const forceClose = vi.fn(async () => undefined);
const onTimeout = vi.fn();
const closing = shutdownRuntime({
closeFeatures: () => durable.promise,
closeProtocol,
forceClose,
onTimeout,
});
await Promise.resolve();
expect(closeProtocol).not.toHaveBeenCalled();
durable.resolve();
await closing;
expect(closeProtocol).toHaveBeenCalledOnce();
expect(forceClose).not.toHaveBeenCalled();
expect(onTimeout).not.toHaveBeenCalled();
});
it('releases features and forcibly closes real stdio when a subscriber stops reading', async () => {
const input = new PassThrough();
const output = new PassThrough({ highWaterMark: 1 });
const transport = new StdioServerTransport(input, output);
const handle = serveStdio(
() =>
new Server(
{ name: 'shutdown-test', version: '1' },
{ capabilities: { resources: { subscribe: true, listChanged: true } } },
),
{ transport },
);
const order: string[] = [];
const onTimeout = vi.fn(() => order.push('timeout'));
const forceClose = vi.fn(async () => {
order.push('force');
await transport.close();
output.destroy();
});
try {
input.write(
`${JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'subscriptions/listen',
params: {
notifications: { resourcesUpdated: ['test://events'] },
_meta: {
'io.modelcontextprotocol/protocolVersion': '2026-07-28',
'io.modelcontextprotocol/clientCapabilities': {},
},
},
})}\n`,
);
await vi.waitFor(() => expect(output.writableLength).toBeGreaterThan(0));
await shutdownRuntime({
closeFeatures: async () => {
order.push('features');
},
closeProtocol: () => {
order.push('protocol');
return handle.close();
},
forceClose,
graceMs: 10,
onTimeout,
});
expect(order).toEqual(['features', 'protocol', 'timeout', 'force']);
expect(forceClose).toHaveBeenCalledOnce();
expect(output.destroyed).toBe(true);
expect(input.listenerCount('data')).toBe(0);
} finally {
await transport.close();
input.destroy();
output.destroy();
}
});
it('still closes the protocol after a feature failure and preserves that error', async () => {
const failure = new Error('feature shutdown failed');
const closeProtocol = vi.fn(async () => undefined);
const forceClose = vi.fn(async () => undefined);
await expect(
shutdownRuntime({
closeFeatures: async () => {
throw failure;
},
closeProtocol,
forceClose,
}),
).rejects.toBe(failure);
expect(closeProtocol).toHaveBeenCalledOnce();
expect(forceClose).not.toHaveBeenCalled();
});
it('preserves all cleanup errors and forces closure after a protocol failure', async () => {
const failures = [new Error('features'), new Error('protocol'), new Error('force')];
await expect(
shutdownRuntime({
closeFeatures: async () => {
throw failures[0];
},
closeProtocol: async () => {
throw failures[1];
},
forceClose: async () => {
throw failures[2];
},
}),
).rejects.toMatchObject({ errors: failures });
});
it('does not skip forced closure when timeout reporting fails', async () => {
const reportingError = new Error('reporting');
const forceClose = vi.fn(async () => undefined);
await expect(
shutdownRuntime({
closeFeatures: async () => undefined,
closeProtocol: () => new Promise<void>(() => undefined),
forceClose,
graceMs: 1,
onTimeout: () => {
throw reportingError;
},
}),
).rejects.toBe(reportingError);
expect(forceClose).toHaveBeenCalledOnce();
});
it('reports a protocol rejection that arrives after the shutdown deadline', async () => {
const protocol = Promise.withResolvers<void>();
const onLateProtocolError = vi.fn();
await shutdownRuntime({
closeFeatures: async () => undefined,
closeProtocol: () => protocol.promise,
forceClose: async () => undefined,
graceMs: 1,
onTimeout: vi.fn(),
onLateProtocolError,
});
const failure = new Error('late protocol failure');
protocol.reject(failure);
await vi.waitFor(() => expect(onLateProtocolError).toHaveBeenCalledWith(failure));
});
});