Mock Server Startup API fails
See original GitHub issueSoftware versions
This has been tested on Windows as well as on macOS
General Library Versions
- @pact-foundation/pact-node: 10.13.1
- @pact-foundation/pact-core: 11.1.0
- deasync: 0.1.22
Windows
- OS: Windows 10
- Node Version: v14.17.4
macOS
- OS: macOS 11.4
- Node Version: v16.6.1
Issue Checklist
Please confirm the following:
- I have upgraded to the latest
- I have the read the FAQs in the Readme
- I have triple checked, that there are no unhandled promises in my code
- I have set my log level to debug and attached a log file showing the complete request/response cycle
- For bonus points and virtual high fives, I have created a reproduceable git repository (see below) to illustrate the problem
Description
During the evaluation of karma-pact (keep reading, it is not a karma or karma-pact issue), we stumbled across a problem: the mock server didn’t become available and karma did shutdown immediately.
The reason was an exception, that we tried to reproduce in an isolated way. To do this, we’ve extracted the core logic and executed it without karma (or anything other besides pact). The following code has been used:
import wrapper from "@pact-foundation/pact-core"
import deasync from "deasync"
import needle from "needle"
var pacts = [{port: 8992}];
// If pact options is object, wrap in array
if (!Array.isArray(pacts)) {
pacts = [pacts];
}
var startingServers = [];
pacts.map(function (pact) {
var server = wrapper.createServer(pact);
server.start().then(function () {
console.log('Pact Mock Server running on port: ' + server.options.port);
// Remove current server from starting servers array
startingServers = startingServers.filter(x => x !== server.options.port);
}, function (err) {
console.error('Error while trying to run karma-pact: ' + err);
});
// Add current server to starting servers array
startingServers.push(server.options.port);
});
deasync.loopWhile(function () {
return !isMockServerReady();
});
function isMockServerReady() {
return startingServers.length === 0;
}
console.log("mock server ready: " + isMockServerReady())
needle.get("http://localhost:8992", {}, function (error, value) {
console.log("value")
console.log(value)
console.log("error")
console.log(error)
});
The application crashes and the mock server never becomes available. The reason seems to be an unhandled error somewhere in the codebase:
internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
Error: connect ECONNREFUSED 127.0.0.1:8992
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1148:16)
(full log further down).
This unhandled exception becomes handled through deasync and thus terminates the process. I suspect that the exception is being caused by __waitForServiceUp()
or __call()
in service.ts
, but was unable to track the exception down.
The code has been tested with @pact-foundation/pact-node@v10.13.1
and @pact-foundation/pact-core@v11.1.0
Expected behaviour
index.js
should be executed without any problems. A request to the mock server should be possible at the end.
Steps to reproduce
The project demonstrating the issue can be found here: https://github.com/fernanfs/pact-playground
Running the example is simple:
- checkout the codebase
- execute
npm install
- run
node index.js
Relevant log files
This is the output generated on Windows when running index.js
:
C:\Workspace\Tools\node-v14.17.4-win-x64\node.exe C:\Workspace\ws\pact-playground\index.js
Debugger listening on ws://127.0.0.1:51885/d1abdb52-1fa6-4819-b57a-9709e94932d1
Debugger attached.
[2021-08-10 13:18:28.098 +0000] INFO (25028 on WPU8L0082869): pact-core@11.1.0: Creating Pact Server with options:
{"port":8992,"dir":"C:\\Workspace\\ws\\pact-playground","pactFileWriteMode":"overwrite","ssl":false,"cors":false,"host":"localhost"}
[2021-08-10 13:18:28.237 +0000] INFO (25028 on WPU8L0082869): pact-core@11.1.0: Removing all Pact servers.
Waiting for the debugger to disconnect...
internal/process/esm_loader.js:74
internalBinding('errors').triggerUncaughtException(
^
Error: connect ECONNREFUSED 127.0.0.1:8992
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1148:16)
at TCPConnectWrap.callbackTrampoline (internal/async_hooks.js:131:17)
at Function.module.exports.loopWhile (C:\Workspace\ws\pact-playground\node_modules\deasync\index.js:71:23)
at file:///C:/Workspace/ws/pact-playground/index.js:28:9
at ModuleJob.run (internal/modules/esm/module_job.js:170:25)
at async Loader.import (internal/modules/esm/loader.js:178:24)
at async Object.loadESM (internal/process/esm_loader.js:68:5)
Emitted 'error' event on ClientRequest instance at:
at Socket.socketErrorListener (_http_client.js:475:9)
at Socket.emit (events.js:400:28)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
at process.runNextTicks [as _tickCallback] (internal/process/task_queues.js:64:3)
at Function.module.exports.loopWhile (C:\Workspace\ws\pact-playground\node_modules\deasync\index.js:70:11)
at file:///C:/Workspace/ws/pact-playground/index.js:28:9
[... lines matching original stack trace ...]
at async Object.loadESM (internal/process/esm_loader.js:68:5) {
errno: -4078,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 8992
}
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:14 (11 by maintainers)
Top GitHub Comments
This is an absolutely awesome report! Super detailed, logs included, tested in OSX and Windows and a reproducible example!? You’re amazing!
I think this might be related to the very last version where needle was introduced. My guess is that
needle.get
is throwing this error, which isn’t caught, because it’s thrown from inside the promise constructor. If that’s the case, it should be an easy fix.Closing this, because thanks to @fernanfs (https://github.com/pact-foundation/karma-pact/pull/27) karma-pact v3.0.0 no longer uses deasync, and it looks like this is a deasync issue rather than a pact issue.