{"_id":"@artian-techs/adonis-orbit","_rev":"3-835fc6e6493db9e77702608f3be8b334","name":"@artian-techs/adonis-orbit","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@artian-techs/adonis-orbit","version":"0.1.0","keywords":["adonisjs","queue","jobs","dashboard"],"author":{"name":"Oussama Benhamed","email":"b.oussama@corposmart.dz"},"license":"MIT","_id":"@artian-techs/adonis-orbit@0.1.0","maintainers":[{"name":"artian-techs","email":"artian.technologies@gmail.com"}],"homepage":"https://github.com/artian-techs/adonis-orbit#readme","bugs":{"url":"https://github.com/artian-techs/adonis-orbit/issues"},"dist":{"shasum":"c3745b39743c9778e7b6b4afe760662f08527314","tarball":"https://registry.npmjs.org/@artian-techs/adonis-orbit/-/adonis-orbit-0.1.0.tgz","fileCount":45,"integrity":"sha512-iaiWg1FLERNS5wXIrSZamFU92EdQzdvifRpPwqFFR6sxYDD2qVJfR7aPAzz3SqGDt+AlynOR+BxiBEYhrZA9Gg==","signatures":[{"sig":"MEYCIQCjYo7Y7aB/2ovs7+LCt/ZQhu1EwnlYwMUgyODGi/32LQIhAI/Oz9UUJwnjZ9Cy+xegQijloXhEWOpJLwRbaQW5TSJY","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75419},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=24.0.0"},"exports":{".":"./build/index.js","./types":"./build/src/types.js","./stubs/*":"./build/stubs/*","./orbit_provider":"./build/providers/orbit_provider.js"},"gitHead":"51b8a35036ed12f4e249c11e7a63e3d1f3e3a315","scripts":{"lint":"eslint .","test":"node --enable-source-maps --import=@poppinss/ts-exec bin/test.ts","build":"pnpm run compile","clean":"del-cli build","checks":"pnpm lint && pnpm typecheck","format":"prettier --write .","compile":"pnpm run clean && tsc","preview":"node --enable-source-maps --import=@poppinss/ts-exec bin/preview.ts","release":"release-it","typecheck":"tsc --noEmit","postcompile":"pnpm run copy:templates","copy:templates":"cpy \"stubs/**/*.stub\" build/stubs && cpy \"templates/**/*.{edge,svg}\" build/templates","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"artian-techs","email":"artian.technologies@gmail.com"},"prettier":"@adonisjs/prettier-config","release-it":{"git":{"push":true,"tagName":"v${version}","commitMessage":"chore(release): ${version}","tagAnnotation":"v${version}","requireUpstream":true,"requireCleanWorkingDir":true},"npm":{"publish":true,"skipChecks":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":{"name":"angular"}}}},"repository":{"url":"git+https://github.com/artian-techs/adonis-orbit.git","type":"git"},"_npmVersion":"11.17.0","description":"See what the queue of AdonisJS does, keep it, and ask a job again.","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"tag":"latest","access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.24.0","devDependencies":{"pg":"^8.23.0","luxon":"^3.5.0","eslint":"^10.8.1","cpy-cli":"^5.0.0","del-cli":"^6.0.0","edge.js":"^6.0.2","prettier":"^3.9.6","@types/pg":"^8.23.1","release-it":"^21.0.2","typescript":"^6.0.3","@types/node":"^24.13.3","@japa/assert":"^4.2.0","@japa/runner":"^5.3.0","@types/luxon":"^3.7.4","@adonisjs/core":"^7.4.0","@adonisjs/lucid":"^22.4.2","@adonisjs/queue":"^0.6.2","@poppinss/ts-exec":"^1.4.4","@adonisjs/tsconfig":"^2.0.0","@adonisjs/assembler":"^8.5.0","@adonisjs/eslint-config":"^3.1.0","@adonisjs/prettier-config":"^1.5.0","@release-it/conventional-changelog":"^12.0.0"},"peerDependencies":{"luxon":"^3.0.0","edge.js":"^6.0.0","@adonisjs/core":"^6.18.0 || ^7.0.0","@adonisjs/lucid":"^21.0.0 || ^22.0.0","@adonisjs/queue":"^0.6.0","@adonisjs/assembler":"^7.0.0 || ^8.0.0"},"peerDependenciesMeta":{"@adonisjs/assembler":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/adonis-orbit_0.1.0_1787279952492_0.6404953930968629","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@artian-techs/adonis-orbit","version":"0.1.1","keywords":["adonisjs","queue","jobs","dashboard"],"author":{"name":"Oussama Benhamed","email":"b.oussama@corposmart.dz"},"license":"MIT","_id":"@artian-techs/adonis-orbit@0.1.1","maintainers":[{"name":"artian-techs","email":"artian.technologies@gmail.com"}],"homepage":"https://github.com/artian-techs/adonis-orbit#readme","bugs":{"url":"https://github.com/artian-techs/adonis-orbit/issues"},"dist":{"shasum":"094e0cff40faba5e3309c7b6b0e84f60d60c4e11","tarball":"https://registry.npmjs.org/@artian-techs/adonis-orbit/-/adonis-orbit-0.1.1.tgz","fileCount":45,"integrity":"sha512-0ItQf+MA2H6tXoGU3+zapZTqHdbFav9aWPIKEv7dHSOTlfmS4MzdFstV+2Poj5prRYYXh4Ldx2jTbyX0O76aaQ==","signatures":[{"sig":"MEUCIQCkAcIjh08aDQE85sPoZFUr0PyODf9vUfisxMRDghezWwIgTAnEpi56eKrNKOliSPq9kp5s8lrHhhGpGHPDjZxscUE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75415},"main":"build/index.js","type":"module","types":"./build/index.d.ts","engines":{"node":">=24.0.0"},"exports":{".":"./build/index.js","./types":"./build/src/types.js","./stubs/*":"./build/stubs/*","./orbit_provider":"./build/providers/orbit_provider.js"},"gitHead":"391a8ebd6f35f10681c88b6849a0b94fbeedacc3","scripts":{"lint":"eslint .","test":"node --enable-source-maps --import=@poppinss/ts-exec bin/test.ts","build":"pnpm run compile","clean":"del-cli build","checks":"pnpm lint && pnpm typecheck","format":"prettier --write .","compile":"pnpm run clean && tsc","preview":"node --enable-source-maps --import=@poppinss/ts-exec bin/preview.ts","release":"release-it","typecheck":"tsc --noEmit","postcompile":"pnpm run copy:templates","copy:templates":"cpy \"stubs/**/*.stub\" build/stubs && cpy \"templates/**/*.{edge,svg}\" build/templates","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"artian-techs","email":"artian.technologies@gmail.com"},"prettier":"@adonisjs/prettier-config","release-it":{"git":{"push":true,"tagName":"v${version}","commitMessage":"chore(release): ${version}","tagAnnotation":"v${version}","requireUpstream":true,"requireCleanWorkingDir":true},"npm":{"publish":true,"skipChecks":true},"github":{"release":true},"plugins":{"@release-it/conventional-changelog":{"preset":{"name":"angular"}}}},"repository":{"url":"git+https://github.com/artian-techs/adonis-orbit.git","type":"git"},"_npmVersion":"11.17.0","description":"See what the queue of AdonisJS does, keep it, and ask a job again.","directories":{},"_nodeVersion":"24.19.0","publishConfig":{"tag":"latest","access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.24.0","devDependencies":{"pg":"^8.23.0","luxon":"^3.5.0","eslint":"^10.8.1","cpy-cli":"^5.0.0","del-cli":"^6.0.0","edge.js":"^6.0.2","prettier":"^3.9.6","@types/pg":"^8.23.1","release-it":"^21.0.2","typescript":"^6.0.3","@types/node":"^24.13.3","@japa/assert":"^4.2.0","@japa/runner":"^5.3.0","@types/luxon":"^3.7.4","@adonisjs/core":"^7.4.0","@adonisjs/lucid":"^22.4.2","@adonisjs/queue":"^0.6.2","@poppinss/ts-exec":"^1.4.4","@adonisjs/tsconfig":"^2.0.0","@adonisjs/assembler":"^8.5.0","@adonisjs/eslint-config":"^3.1.0","@adonisjs/prettier-config":"^1.5.0","@release-it/conventional-changelog":"^12.0.0"},"peerDependencies":{"luxon":"^3.0.0","edge.js":"^6.0.0","@adonisjs/core":"^6.18.0 || ^7.0.0","@adonisjs/lucid":"^21.0.0 || ^22.0.0","@adonisjs/queue":"^0.6.0","@adonisjs/assembler":"^7.0.0 || ^8.0.0"},"peerDependenciesMeta":{"@adonisjs/assembler":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/adonis-orbit_0.1.1_1787280749996_0.7774606625692646","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@artian-techs/adonis-orbit","version":"0.2.0","type":"module","description":"See what the queue of AdonisJS does, keep it, and ask a job again.","main":"build/index.js","exports":{".":"./build/index.js","./types":"./build/src/types.js","./orbit_provider":"./build/providers/orbit_provider.js","./stubs/*":"./build/stubs/*"},"scripts":{"build":"pnpm run compile","clean":"del-cli build","compile":"pnpm run clean && tsc","copy:templates":"cpy \"stubs/**/*.stub\" build/stubs && cpy \"templates/**/*.{edge,svg}\" build/templates","postcompile":"pnpm run copy:templates","test":"node --enable-source-maps --import=@poppinss/ts-exec bin/test.ts","preview":"node --enable-source-maps --import=@poppinss/ts-exec bin/preview.ts","typecheck":"tsc --noEmit","lint":"eslint .","format":"prettier --write .","checks":"pnpm lint && pnpm typecheck","prepublishOnly":"pnpm run build","release":"release-it"},"prettier":"@adonisjs/prettier-config","keywords":["adonisjs","queue","jobs","dashboard"],"license":"MIT","author":{"name":"Oussama Benhamed","email":"b.oussama@corposmart.dz"},"homepage":"https://github.com/artian-techs/adonis-orbit#readme","repository":{"type":"git","url":"git+https://github.com/artian-techs/adonis-orbit.git"},"bugs":{"url":"https://github.com/artian-techs/adonis-orbit/issues"},"packageManager":"pnpm@10.24.0","engines":{"node":">=24.0.0"},"peerDependencies":{"@adonisjs/assembler":"^7.0.0 || ^8.0.0","@adonisjs/core":"^6.18.0 || ^7.0.0","@adonisjs/lucid":"^21.0.0 || ^22.0.0","@adonisjs/queue":"^0.6.0","edge.js":"^6.0.0","luxon":"^3.0.0"},"devDependencies":{"@adonisjs/assembler":"^8.5.0","@adonisjs/core":"^7.4.0","@adonisjs/eslint-config":"^3.1.0","@adonisjs/lucid":"^22.4.2","@adonisjs/prettier-config":"^1.5.0","@adonisjs/queue":"^0.6.2","@adonisjs/tsconfig":"^2.0.0","@japa/assert":"^4.2.0","@japa/runner":"^5.3.0","@poppinss/ts-exec":"^1.4.4","@release-it/conventional-changelog":"^12.0.0","@types/luxon":"^3.7.4","@types/node":"^24.13.3","@types/pg":"^8.23.1","cpy-cli":"^5.0.0","del-cli":"^6.0.0","edge.js":"^6.0.2","eslint":"^10.8.1","luxon":"^3.5.0","pg":"^8.23.0","prettier":"^3.9.6","release-it":"^21.0.2","typescript":"^6.0.3"},"peerDependenciesMeta":{"@adonisjs/assembler":{"optional":true}},"publishConfig":{"access":"public","tag":"latest"},"release-it":{"git":{"requireCleanWorkingDir":true,"requireUpstream":true,"commitMessage":"chore(release): ${version}","tagAnnotation":"v${version}","push":true,"tagName":"v${version}"},"github":{"release":true},"npm":{"publish":true,"skipChecks":true},"plugins":{"@release-it/conventional-changelog":{"preset":{"name":"angular"}}}},"gitHead":"dd4165c17e357bdd6e7f24a0baf956e40e439cba","types":"./build/index.d.ts","_id":"@artian-techs/adonis-orbit@0.2.0","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-9ve7Bz2WY0USoQislMcTjLN8Qb6WSP+ggbkmNbwe3qatqzwJSIJHzXajBEVwZG7yvmbSGbutI0xBYOuHud6z0A==","shasum":"10e1e02b34fcde2592cccf6dd3330e96dbd6c899","tarball":"https://registry.npmjs.org/@artian-techs/adonis-orbit/-/adonis-orbit-0.2.0.tgz","fileCount":50,"unpackedSize":92877,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCHSgU+/T9HU3XplpZPfF3dqhRubzycixXtOLul5l07awIhAOilMGMs9P8C3N6HrvwjWL5TpiOsPo/YbWg+fIkNQlhI"}]},"_npmUser":{"name":"artian-techs","email":"artian.technologies@gmail.com"},"directories":{},"maintainers":[{"name":"artian-techs","email":"artian.technologies@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/adonis-orbit_0.2.0_1787336979965_0.6467022725286029"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-21T02:39:12.250Z","modified":"2026-08-21T18:29:40.295Z","0.1.0":"2026-08-21T02:39:12.650Z","0.1.1":"2026-08-21T02:52:30.155Z","0.2.0":"2026-08-21T18:29:40.105Z"},"bugs":{"url":"https://github.com/artian-techs/adonis-orbit/issues"},"author":{"name":"Oussama Benhamed","email":"b.oussama@corposmart.dz"},"license":"MIT","homepage":"https://github.com/artian-techs/adonis-orbit#readme","keywords":["adonisjs","queue","jobs","dashboard"],"repository":{"type":"git","url":"git+https://github.com/artian-techs/adonis-orbit.git"},"description":"See what the queue of AdonisJS does, keep it, and ask a job again.","maintainers":[{"name":"artian-techs","email":"artian.technologies@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\"templates/orbit.svg\" width=\"96\" alt=\"Orbit\">\n</p>\n\n# adonis-orbit\n\nWhat the queue of AdonisJS did with each job, kept in a table, read on a page,\nand asked again when it failed.\n\nThe queue holds its jobs in Redis and lets them go when they end. This package\nlistens to the channels that the queue publishes, writes one row for each job,\nand serves a page that reads the table. A job that failed keeps the values it\ncarried, so a person can ask for it again — from the page, or from a command.\n\nIt works with AdonisJS 6 and 7.\n\n## Install\n\n```bash\npnpm add @artian-techs/adonis-orbit\nnode ace configure @artian-techs/adonis-orbit\nnode ace migration:run\n```\n\nThe configure step writes the provider in `adonisrc.ts`, publishes\n`config/orbit.ts`, publishes the two migrations — the table of the jobs, and\nthe one that names the silenced classes — and declares the two environment\nvariables that guard the page.\n\n## The page\n\n```\nhttp://localhost:3333/queue\n```\n\nIt asks for a name and a word, in Basic auth. **While one of the two is\nmissing, the page answers \"not found\"**: a machine that carries neither shows\nnothing.\n\nThe page holds no session on purpose: it belongs to the team that runs the\nmachine, not to the users of the application. It speaks English only.\n\nA menu on the left leads to each view, and carries the count of each status.\nUnder it, one button reads the page in the light or in the dark. The page reads\nthe mode of the machine while nobody chose; a choice is held in a cookie. The\npage holds no JavaScript.\n\nThe list carries a pager over the table and under it: the number of every page\nthat stands near the one that is read, the first, the last, and a gap between\nthem. **Rows** says how many jobs one page holds — 25, 50 or 100. The choice is\nheld in a cookie, thus the menu carries it from one status to the next. Without\none, fifty.\n\n| Entry | What it shows |\n| --- | --- |\n| Overview | four numbers, then the last jobs of every status |\n| Pending, Running, Retrying, Completed, Failed, Lost | the same list, of one status |\n| Silenced | the classes that the lists leave out |\n| Metrics | what each class and each queue cost over the last 24 hours |\n\nThe four numbers of the overview:\n\n| Number | What it counts |\n| --- | --- |\n| Jobs per minute | the jobs that ended in the last minute |\n| Jobs past hour | the jobs that ended in the last hour |\n| Failed jobs past 7 days | the jobs whose last try fell |\n| Jobs running now | the jobs a worker holds at this moment |\n\nMetrics reads the same table: for each class and for each queue, how many jobs\nended, how many fell, and the average and the longest of their durations.\n\n## Silence a job\n\nA job that runs every minute fills the list and hides the rest. The button\n**Silence** on any row takes its class out of the lists, and out of the counts\nof the menu.\n\nNothing else changes: the worker keeps its work, and the table keeps its trace.\nThe page **Silenced** shows what is left out, and **Show again** brings the\nclass back — with everything it did while it was silent.\n\n## Configuration\n\n```ts\nimport { DatabaseSink, basicAuth, defineConfig } from '@artian-techs/adonis-orbit'\n\nimport env from '#start/env'\n\nexport default defineConfig({\n  path: '/queue',\n\n  authorize: basicAuth({\n    user: env.get('ORBIT_DASHBOARD_USER'),\n    password: env.get('ORBIT_DASHBOARD_PASSWORD'),\n  }),\n\n  sinks: [new DatabaseSink()],\n})\n```\n\n## Who may read the page\n\n`authorize` reads the request and answers `true` or `false`. It answers `false`,\nand the page says \"not found\": a machine that guards nothing shows nothing.\n\n`basicAuth` asks for a name and a word, with no session. It is what the\nconfigure step writes, and it answers \"not found\" while one of the two is\nmissing.\n\nAn application that already knows who is asking writes its own guard:\n\n```ts\nconst TEAM = ['someone@example.com', 'someone-else@example.com']\n\nexport default defineConfig({\n  path: '/queue',\n\n  authorize: async ({ auth }) => {\n    await auth.check()\n\n    return TEAM.includes(auth.user?.email ?? '')\n  },\n\n  sinks: [new DatabaseSink()],\n})\n```\n\nThe package imports no authentication of its own: the guard reads the context\nof the request, and the application says what it reads there.\n\nA guard that wants to say something other than \"not found\" writes its answer\nbefore it says `false`:\n\n```ts\nauthorize: async (ctx) => {\n  if (await ctx.auth.check()) {\n    return true\n  }\n\n  ctx.response.redirect('/login')\n\n  return false\n}\n```\n\n## Where the trace goes\n\n**Nothing is kept that the configuration does not name.** The table of\n`job_runs` is one sink among others, and the configure step writes it in\n`config/orbit.ts`:\n\n```ts\nimport { DatabaseSink, defineConfig } from '@artian-techs/adonis-orbit'\n\nexport default defineConfig({\n  path: '/queue',\n  auth: { user: env.get('ORBIT_DASHBOARD_USER'), password: env.get('ORBIT_DASHBOARD_PASSWORD') },\n\n  sinks: [new DatabaseSink(), new MySink()],\n})\n```\n\nTake `DatabaseSink` away, and the table stays empty and the page shows nothing:\nthe page reads the table, and reads nothing else. A machine that sends its\ntrace somewhere else thus keeps none of it.\n\nA sink reads one step of one job, and gives nothing back:\n\n```ts\nimport type { JobEvent, Sink } from '@artian-techs/adonis-orbit'\n\nclass MySink implements Sink {\n  async write(events: JobEvent[]) {\n    // { type: 'dispatched' | 'started' | 'finished', at, job: { id, name, queue, payload, attempts } }\n  }\n}\n```\n\nThe events of one step arrive together: a dispatch of ten jobs calls `write`\nonce, with ten events. A sink that fails is written in the log, and the job\nthat runs goes on.\n\n## What of the payload is kept\n\nA payload holds what a person wrote: an address, a name, a number. The\nconfiguration says how much of it the trace keeps.\n\n```ts\nexport default defineConfig({\n  // ...\n\n  /** 'full' by default. 'none' keeps nothing. */\n  payload: (payload, job) => ({ ...payload, password: undefined }),\n})\n```\n\nThe rule is applied before the first sink reads the event, thus what it takes\nout reaches nothing and nobody.\n\n## What the table holds\n\nOne row for one job, completed at each step.\n\n| Status | What it says |\n| --- | --- |\n| `pending` | the job waits for a worker |\n| `running` | a worker holds it |\n| `retrying` | a try failed, the next one is set |\n| `completed` | done |\n| `failed` | every try fell |\n| `lost` | the queue let the job go, and no worker said how it ended |\n\nThe row that the dispatch writes and the row that the worker writes are the\nsame row. Either of the two can arrive first, thus the first one writes and the\nsecond one completes.\n\n## Ask a job again\n\nFrom the page, with the button on a row that failed or that the queue lost. Or\nwith the job that the package carries:\n\n```ts\nimport { JobRun, JobRunStatus, retryRun } from '@artian-techs/adonis-orbit'\n\nconst runs = await JobRun.query().where('status', JobRunStatus.FAILED)\n\nfor (const run of runs) {\n  await retryRun(run)\n}\n```\n\nThe row is never replaced: the new job takes a new identifier and opens its own\nrow, and the old one names it.\n\n## Tests\n\n```bash\npnpm test\n```\n\nThe tests read a PostgreSQL server, as the package does. The environment names\nit, and without it the tests read `127.0.0.1:5432` and the database\n`orbit_test`:\n\n| Variable | What it names |\n| --- | --- |\n| `PG_HOST` | the machine, `127.0.0.1` |\n| `PG_PORT` | the port, `5432` |\n| `PG_USER` | the name, `postgres` |\n| `PG_PASSWORD` | the word, `postgres` |\n| `PG_DATABASE` | the database, `orbit_test` |\n\nA server for the tests alone:\n\n```bash\ndocker run -d --name orbit-test-pg -p 55432:5432 \\\n  -e POSTGRES_USER=orbit -e POSTGRES_PASSWORD=orbit -e POSTGRES_DB=orbit_test \\\n  postgres:16\n\nPG_PORT=55432 PG_USER=orbit PG_PASSWORD=orbit pnpm test\n```\n\nThe tests create the two tables from the stubs of `stubs/migrations`, and take\nthem away at the end.\n\n`pnpm preview` opens the page on `http://localhost:3333/queue`, with jobs of\nevery status to read and the name `orbit` and the word `orbit`. It reads a\ndatabase of its own, `orbit_preview`, and makes it if it is not there.\n\n## Close the rows that wait for nothing\n\nA worker publishes what it does, and Orbit reads it. A worker that refuses a\njob **before it starts** publishes nothing: it fails the job in the queue and\ntakes the next one. This happens at every deployment where the worker restarts\nafter the API, because the worker of the old build does not carry the class\nthat the new API asks for.\n\nThe row of that job stays `pending`, and the page shows a job that waits for a\nworker that will never take it.\n\n`ReconcileJobRuns` asks the queue about every row that stayed open too long:\n\n```ts\nimport { ReconcileJobRuns } from '@artian-techs/adonis-orbit'\n\nawait ReconcileJobRuns.schedule({ minutes: 5 }).cron('* * * * *').run()\n```\n\n- the queue holds the job, thus the row is right and stays as it is;\n- the queue holds the answer, thus the row takes it, with its error;\n- the queue holds nothing, thus the row becomes `lost`.\n\n`minutes` says how long a row stays open before the queue is asked about it.\nIt leaves the events of the worker the time to land: a row that a worker closed\na second ago is never read. Without it, five minutes.\n\nThe rows are read from the table, thus this needs `DatabaseSink`. The answers\ngo to every sink of the configuration, as the events of the worker do.\n\nA queue that keeps its failed jobs gives the error that stopped them. Ask for\nit in `config/queue.ts`, else the queue removes a job as soon as it fails and\nthe row can only say `lost`:\n\n```ts\ndefaultJobOptions: { removeOnFail: false },\n```\n\n## Take out the traces that ended well\n\nThe package carries `PruneJobRuns` and names it to the queue itself. Give it a\nplace in the schedule of the application:\n\n```ts\nimport { PruneJobRuns } from '@artian-techs/adonis-orbit'\n\nawait PruneJobRuns.schedule({ days: 7 }).cron('10 0 * * *').run()\n```\n\nA row that failed is never taken out.\n","readmeFilename":"README.md"}