-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
Add support for passing request to a worker thread using a simple wrapper function. ``` micri(handler); ``` becomes ``` micri(withWorker(handler)); ```
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
!node_modules | ||
/micri | ||
/lib |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Worker Threads | ||
============== | ||
|
||
Two concurrent requests running a CPU intensive request method in the | ||
main thread: | ||
|
||
``` | ||
~% time curl 127.0.0.1:3000/main | ||
299993curl 127.0.0.1:3000/main 0.01s user 0.00s system 0% cpu 8.791 total | ||
~% time curl 127.0.0.1:3000/main | ||
299993curl 127.0.0.1:3000/main 0.00s user 0.00s system 0% cpu 16.547 total | ||
``` | ||
|
||
Two concurrent requests running a CPU intensive request method in worker | ||
threads: | ||
|
||
``` | ||
~% time curl 127.0.0.1:3000/worker | ||
299993curl 127.0.0.1:3000/worker 0.00s user 0.00s system 0% cpu 9.025 total | ||
~% time curl 127.0.0.1:3000/worker | ||
299993curl 127.0.0.1:3000/worker 0.00s user 0.00s system 0% cpu 9.026 total | ||
``` |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "router", | ||
"description": "Router example", | ||
"main": "lib/index.js", | ||
"scripts": { | ||
"build": "rm -rf ./lib ./micri && mkdir ./micri && cp ../../dist/* ./micri && tsc", | ||
"start": "node lib/" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "12.7.11", | ||
"typescript": "3.6.3" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import path from 'path' | ||
import { parse } from 'url'; | ||
import micri, { | ||
IncomingMessage, | ||
ServerResponse, | ||
Router, | ||
send, | ||
withWorker | ||
} from 'micri'; | ||
import prime from './prime'; | ||
|
||
const { router, on, otherwise } = Router; | ||
|
||
const parsePath = (req: IncomingMessage): string => parse(req.url || '/').path || '/'; | ||
|
||
micri(router( | ||
on.get((req: IncomingMessage) => parsePath(req) === '/main', prime), | ||
on.get((req: IncomingMessage) => parsePath(req) === '/worker', withWorker(path.join(__dirname, './prime.js'))), | ||
on.get((req: IncomingMessage) => parsePath(req) === '/stream', withWorker(path.join(__dirname, './stream.js'))), | ||
otherwise((_req: IncomingMessage, res: ServerResponse) => send(res, 400, 'Method Not Accepted')))) | ||
.listen(3000); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
export default function fn() { | ||
const limit = 3e5; | ||
let r; | ||
|
||
for (let n = 2; n <= limit; n++) { | ||
let isPrime = true; | ||
for(let factor = 2; factor < n; factor++) { | ||
if(n % factor == 0) { | ||
isPrime = false; | ||
break; | ||
} | ||
} | ||
if(isPrime) { | ||
r = n; | ||
} | ||
} | ||
|
||
return r; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { IncomingMessage, ServerResponse } from "http"; | ||
|
||
function getNumber() { | ||
return new Promise((resolve) => { | ||
setTimeout(() => { | ||
const x = Math.round(Math.random() * 100); | ||
|
||
resolve(x); | ||
}, 300); | ||
}); | ||
} | ||
|
||
export default async function wrkStream(_req: IncomingMessage, res: ServerResponse) { | ||
res.writeHead(200, { | ||
'X-Custom-Header': "I'm a header" | ||
}); | ||
|
||
for (let i = 0; i < 30; i++) { | ||
const x = await getNumber(); | ||
res.write(`${x}\n`); | ||
} | ||
res.end(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"compilerOptions": { | ||
"declaration": true, | ||
"esModuleInterop": true, | ||
"lib": ["esnext"], | ||
"module": "CommonJS", | ||
"moduleResolution": "node", | ||
"resolveJsonModule": true, | ||
"strictNullChecks": true, | ||
"noImplicitAny": true, | ||
"noUnusedLocals": true, | ||
"noUnusedParameters": true, | ||
"outDir": "./lib", | ||
"strict": true, | ||
"target": "ES2018", | ||
"inlineSourceMap": true, | ||
"types": ["node"], | ||
"typeRoots": [ | ||
"./node_modules/@types" | ||
] | ||
}, | ||
"include": ["./src"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
# yarn lockfile v1 | ||
|
||
|
||
"@types/[email protected]": | ||
version "12.7.11" | ||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446" | ||
integrity sha512-Otxmr2rrZLKRYIybtdG/sgeO+tHY20GxeDjcGmUnmmlCWyEnv2a2x1ZXBo3BTec4OiTXMQCiazB8NMBf0iRlFw== | ||
|
||
[email protected]: | ||
version "3.6.3" | ||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da" | ||
integrity sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
const { serve } = require('./index'); | ||
const { request } = require('http'); | ||
const { parentPort, workerData } = require('worker_threads'); | ||
|
||
module.exports = async function wrap(fn) { | ||
try { | ||
const buf = await new Promise((resolve) => { | ||
parentPort.on('message', (body) => resolve(body)); | ||
}); | ||
|
||
const server = serve(fn); | ||
server.listen(() => { | ||
const port = server.address().port; | ||
const intReq = request( | ||
`http://127.0.0.1${workerData.req.url}`, | ||
{ | ||
hostname: '127.0.0.1', | ||
port, | ||
method: workerData.req.method, | ||
headers: { | ||
...workerData.req.headers, | ||
'Content-Length': buf.length, | ||
}, | ||
}, | ||
(res) => { | ||
const head = { | ||
statusCode: res.statusCode || 200, | ||
statusMessage: res.statusMessage, | ||
headers: res.headers, | ||
}; | ||
|
||
parentPort.postMessage(head); | ||
|
||
res.on('data', (chunk) => { | ||
parentPort.postMessage(chunk); | ||
}); | ||
res.on('end', () => { | ||
process.exit(0); | ||
}); | ||
} | ||
); | ||
intReq.on('error', (err) => { | ||
console.error(err); | ||
process.exit(1); | ||
}); | ||
|
||
intReq.write(Buffer.from(buf)); | ||
intReq.end(); | ||
}); | ||
} catch (err) { | ||
console.error(err); | ||
process.exit(1); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
// Utilities | ||
import { serve } from './serve'; | ||
import * as Router from './router'; | ||
import withWorker from './with-worker'; | ||
|
||
export default serve; | ||
export * from './body'; | ||
export * from './serve'; | ||
export * from './types'; | ||
export { Router }; | ||
export { withWorker }; | ||
export { MicriError } from './errors'; |