Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions docs/open-collection-gap-analysis/AGENT_PROGRESS.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions examples/demo-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Missio Demo API

The demo collection is local-only and does not require internet access for protocol fixtures.

Start the HTTP, GraphQL, WebSocket, runtime, auth, redirect, and binary upload fixture:

```powershell
node examples/demo-api/server.js
```

Start the gRPC fixture in a second terminal before sending requests under `examples/demo-api/gRPC/`:

```powershell
node examples/demo-api/grpc-server.js
```

The gRPC fixture binds `127.0.0.1:50051`, matching `LOCAL.grpcBaseUrl=localhost:50051` in `opencollection.yml`. If a gRPC demo request reports `UNAVAILABLE` or `ECONNREFUSED`, start or restart that fixture and retry with the LOCAL environment selected.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/chat-users-bidi-streaming.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ grpc:
"requestId": "{{grpcRequestId}}-chat-2"
}
}
docs: Run `node examples/demo-api/grpc-server.js`, select the LOCAL environment, then send this bidirectional-streaming gRPC request.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this bidirectional-streaming gRPC request to `LOCAL.grpcBaseUrl=localhost:50051`.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/echo-metadata-defaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ grpc:
"requestId": "{{grpcRequestId}}"
}
}
docs: Run `node examples/demo-api/grpc-server.js` to verify collection, folder, and request metadata merging.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this unary gRPC request to verify collection, folder, and request metadata merging at `localhost:50051`.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/echo-unary.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ runtime:
auth:
type: bearer
token: "{{grpcToken}}"
docs: Run `node examples/demo-api/grpc-server.js`, select the LOCAL environment, then send this unary gRPC request.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this unary gRPC request to `LOCAL.grpcBaseUrl=localhost:50051`.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/folder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ request:
metadata:
- name: x-demo-folder
value: folder-{{grpcRequestId}}
docs: Run `node examples/demo-api/grpc-server.js` before sending these local gRPC requests.
docs: From the repository root, run `node examples/demo-api/grpc-server.js` before sending these local gRPC requests. The fixture binds `127.0.0.1:50051`, matching `LOCAL.grpcBaseUrl=localhost:50051`.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/runtime-unary-lifecycle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ runtime:
variable:
scope: runtime
name: grpcRuntimeRequestId
docs: Run `node examples/demo-api/grpc-server.js`, select the LOCAL environment, optionally edit the request Runtime tab, then send to see unary gRPC metadata/message mutation plus runtime tests, assertions, logs, and set-variable actions.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, optionally edit the request Runtime tab, then send to `LOCAL.grpcBaseUrl=localhost:50051` to see unary gRPC metadata/message mutation plus runtime tests, assertions, logs, and set-variable actions.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/stream-users-error.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ grpc:
"requestId": "{{grpcRequestId}}-error"
}
}
docs: Run `node examples/demo-api/grpc-server.js`; this server-streaming request emits one response and then a deterministic gRPC INTERNAL error for diagnostics testing.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this server-streaming request. It emits one response from `localhost:50051` and then a deterministic gRPC INTERNAL error for diagnostics testing.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/stream-users.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ grpc:
"requestId": "{{grpcRequestId}}"
}
}
docs: Run `node examples/demo-api/grpc-server.js`, select the LOCAL environment, then send this server-streaming gRPC request.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this server-streaming gRPC request to `LOCAL.grpcBaseUrl=localhost:50051`.
2 changes: 1 addition & 1 deletion examples/demo-api/gRPC/upload-users-client-streaming.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ runtime:
auth:
type: bearer
token: "{{grpcToken}}"
docs: Run `node examples/demo-api/grpc-server.js`, select the LOCAL environment, then send this client-streaming gRPC request.
docs: Run `node examples/demo-api/grpc-server.js` from the repository root, select the LOCAL environment, then send this client-streaming gRPC request to `LOCAL.grpcBaseUrl=localhost:50051`.
43 changes: 40 additions & 3 deletions examples/demo-api/grpc-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const HOST = '127.0.0.1';
const PORT = 50051;
const PORT = Number(process.env.MISSIO_GRPC_PORT ?? '50051');
if (!Number.isInteger(PORT) || PORT < 0 || PORT > 65535) {
console.error(`Invalid MISSIO_GRPC_PORT value: ${process.env.MISSIO_GRPC_PORT}`);
process.exit(1);
}
const ADDRESS = `${HOST}:${PORT}`;
const PROTO_DIR = path.join(__dirname, 'proto');
const PROTO_PATH = path.join(PROTO_DIR, 'services', 'missio_demo.proto');
Expand Down Expand Up @@ -98,19 +102,52 @@ server.addService(proto.DemoService.service, {
streamUsersWithError,
});

let shutdownStarted = false;

function shutdown(signal) {
if (shutdownStarted) return;
shutdownStarted = true;
console.log(`Received ${signal}; shutting down the gRPC demo server.`);

const forceTimer = setTimeout(() => {
console.error('Graceful gRPC shutdown timed out; forcing shutdown.');
server.forceShutdown();
process.exitCode = 1;
}, 2_000);
forceTimer.unref();

server.tryShutdown((error) => {
clearTimeout(forceTimer);
if (error) {
console.error(error);
server.forceShutdown();
process.exitCode = 1;
return;
}
console.log('Missio gRPC Demo Server stopped.');
});
}

server.bindAsync(ADDRESS, grpc.ServerCredentials.createInsecure(), (err, port) => {
if (err) {
console.error(err);
process.exit(1);
}
server.start();
console.log(`Missio gRPC Demo Server -> ${ADDRESS}`);
process.once('SIGINT', () => shutdown('SIGINT'));
process.once('SIGTERM', () => shutdown('SIGTERM'));
const boundAddress = `${HOST}:${port}`;
console.log(`Missio gRPC Demo Server -> ${boundAddress}`);
console.log('Start command: node examples/demo-api/grpc-server.js');
console.log(port === 50051
? 'OpenCollection LOCAL.grpcBaseUrl: localhost:50051'
: `OpenCollection LOCAL.grpcBaseUrl override for this process: ${boundAddress}`);
console.log(`Proto: ${PROTO_PATH}`);
console.log('Methods:');
console.log(' missio.demo.DemoService/EchoUnary');
console.log(' missio.demo.DemoService/StreamUsers');
console.log(' missio.demo.DemoService/UploadUsers');
console.log(' missio.demo.DemoService/ChatUsers');
console.log(' missio.demo.DemoService/StreamUsersWithError');
console.log(`Listening on ${HOST}:${port}. Press Ctrl+C to stop.`);
console.log(`Listening on ${boundAddress}. Press Ctrl+C to stop.`);
});
7 changes: 7 additions & 0 deletions examples/demo-api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
*
* Runs on http://localhost:3456
*
* gRPC demo requests use a separate local fixture:
* node examples/demo-api/grpc-server.js
* It binds 127.0.0.1:50051, matching LOCAL.grpcBaseUrl in opencollection.yml.
*
* Routes:
* GET /health – liveness check
* POST /upload – accepts any binary body, returns upload info as JSON
Expand Down Expand Up @@ -496,6 +500,9 @@ server.listen(PORT, '127.0.0.1', () => {
console.log(` WS ws://localhost:${PORT}/ws/push (server push after connect)`);
console.log(` WS ws://localhost:${PORT}/ws/close (deterministic server close)`);
console.log(` WS ws://localhost:${PORT}/ws/reject (deterministic upgrade rejection)`);
console.log('\ngRPC demo requests:');
console.log(' Start the separate gRPC fixture: node examples/demo-api/grpc-server.js');
console.log(' It binds 127.0.0.1:50051, matching LOCAL.grpcBaseUrl=localhost:50051.');
console.log('\nFixture files for demo requests:');
console.log(` ${path.join(FIXTURES_DIR, 'sample.png')}`);
console.log(` ${path.join(FIXTURES_DIR, 'sample.txt')}`);
Expand Down
Loading
Loading