Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix: node worker (supposedly) OOM
This fixes an issue where the piscina worker pool crashes with
`FATAL ERROR: v8::FromJust Maybe value is Nothing`

Supposedly, this is the worker running out of memory? No idea. As a fix,
we explicitly pick boundaries for queue and thread size in piscina.
  • Loading branch information
tstelzer committed Jul 8, 2022
commit d8784a65869d5c4c164c197bf13c038a4d0329f5
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ export const fetchAllDocuments = ({
}
const res = These.result(a)
if (E.isLeft(res)) {
errors = Chunk.append_(errors, res.left)
// FIXME: type
errors = Chunk.append_(errors, FetchDataError.fromSerialized(res.left as unknown as any))
} else {
values = Chunk.append_(values, res.right.tuple[0])
const warning = res.right.tuple[1]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { provideDummyTracing } from '@contentlayer/utils'
import { pipe, provideConsole, T } from '@contentlayer/utils/effect'
import type { _A, _E } from '@effect-ts/core/Utils'
import fs from 'node:fs'
import * as os from 'node:os'
import Pool from 'piscina'

import * as _ from './makeCacheItemFromFilePath.js'
Expand All @@ -14,27 +16,33 @@ export type Either<E, A> = Left<E, A> | Right<E, A>
type DTO = Either<_E<ReturnType<F>>, _A<ReturnType<F>>>

// FIXME: naming
// This runs on the host, what is passed into the worker at `pool.run` has to
// be serializable.
export function fromWorkerPool(): F {
// I believe, by default, #workers = #cpu cores, which is probably what we want?
const l = os.cpus().length
const pool = new Pool({
// "Our testing has shown that a maxQueue size of approximately the square
// of the maximum number of threads is generally sufficient and performs
// well for many cases"
//
// via https://github.com/piscinajs/piscina#queue-size
maxQueue: l ** l,
maxThreads: l,
// FIXME: get path dynamically
filename:
'/home/ts/dev/code/contentlayer/packages/@contentlayer/source-files/dist/fetchData/makeCacheItemFromFilePath.worker.js',
})

return (payload) =>
pipe(
T.succeedWith(() => JSON.stringify(payload)),
// host -> worker
T.succeedWith(() => JSON.stringify(payload, null, 2)),
T.chain((value) => T.promise<string>(() => pool.run(value, { name: 'makeCacheItemFromFilePath' }))),
// worker -> host
T.chain((value) => T.succeedWith<DTO>(() => JSON.parse(value))),
T.chain(({ _tag, value }) =>
T.if_(
_tag === 'right',
// FIXME: effect
() => T.succeedWith(() => value),
// FIXME: Signature claims it doesn't fail.
// Signature claims it doesn't fail, so we're just dying here.
() => T.die(value),
),
),
Expand All @@ -54,6 +62,6 @@ export function makeCacheItemFromFilePath(payload: string): Promise<string> {
provideConsole,
provideDummyTracing,
T.runPromise,
(p) => p.then((value) => JSON.stringify(value)),
(p) => p.then((value) => JSON.stringify(value, null, 2)),
)
}