[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GXAFCW13ES3HTREVB5AM0W":3,"skill-same:01M6GXAFCW13ES3HTREVB5AM0W":82},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6GXAFCW13ES3HTREVB5AM0W","add-a-kill-switch-to-a-runaway-job",null,"Use when a long-running job, migration or agent loop can run away and needs a stop an operator can pull in seconds — checked cooperatively at safe points, not via a hard SIGKILL.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",80,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"add a kill switch to a runaway job","add","kill","switch","running","safe","when","at","can","via","long","away","stop","migration","use","agent loop","loop","operator","pull","run","2026-11-10 10:12:30",false,"---\nname: add-a-kill-switch-to-a-runaway-job\ndescription: Use when a long-running job, migration or agent loop can run away and needs a stop an operator can pull in seconds — checked cooperatively at safe points, not via a hard SIGKILL.\n---\n\n# Add a kill switch to a runaway job\n\nA job with no stop button is controlled only by `kill -9`, which leaves work half-applied and state inconsistent. Give the operator a cooperative switch that is polled at safe points, so the job stops after the current unit of work and lands in a resumable state.\n\n## Procedure\n\n1. Define the switch as an out-of-band signal the process can read cheaply: a file, a Redis key, a DB row, or an env var the supervisor can rewrite. File on a shared volume is the simplest:\n       KILL_FILE=\u002Fvar\u002Frun\u002Fbatch\u002Fjob.stop\n       test -f \"$KILL_FILE\" && echo stopping\n\n2. Poll it at a *safe point* — between items, not mid-write. Once per N items and once per outer loop iteration is enough; checking every microsecond wastes the very budget you are protecting:\n       for i, item := range items {\n         if i % 100 == 0 && stopped() { saveCheckpoint(i); return ErrStopped }\n         process(item)\n       }\n\n3. Make the stop idempotent and resumable: persist a checkpoint (`last_processed_id`, offset, cursor) before returning, so a restart continues instead of reprocessing or skipping. Write the checkpoint *after* the side effect commits.\n\n4. Handle `SIGTERM` the same way, so a normal `kubectl delete pod` also stops cleanly. Kubernetes sends `SIGTERM`, waits `terminationGracePeriodSeconds` (default 30), then `SIGKILL`s. Your handler must finish the current unit inside that window:\n       signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)\n       \u002F\u002F set stop flag; do NOT os.Exit mid-write\n\n5. Set the grace window to match: `terminationGracePeriodSeconds: 60` when one unit can take 20 s. A job whose unit of work exceeds the grace window is killed mid-write no matter how good the handler is.\n\n6. Make the switch also pause intake, not just the current worker: a queue consumer should stop pulling new messages (`consumer.pause()`) so stopping does not race a refill.\n\n7. Log the stop with the checkpoint and the count processed, then exit non-zero so the orchestrator records a deliberate stop rather than a success:\n       log.Printf(\"stopped by switch at=%d processed=%d\", i, i)\n\n## Pitfalls\n\n- Checking the switch only at the *end* of the whole job, so it does nothing until the runaway has already finished the damage.\n- Returning immediately without a checkpoint, so the restart reprocesses from zero — or worse, resumes past unprocessed items.\n- `os.Exit(0)` inside the loop, reporting success and skipping deferred cleanup (closing files, releasing locks, flushing).\n- A file switch on a filesystem the worker container does not share, so the operator's `touch` is invisible to the process.\n\n## Verification\n\n    # start the job, let it reach steady state, then pull the switch\n    touch \"$KILL_FILE\"\n    # expect: logs \"stopped by switch at=\u003Cn>\", exit code non-zero, within the grace window\n    ps -o pid,stat,etime -p \"$(pgrep -f batch-job)\"\n    # restart and confirm it resumes from the checkpoint, not from row 0\n    grep checkpoint \u002Fvar\u002Flib\u002Fbatch\u002Fstate.json\n\nReport: the switch mechanism, the poll cadence and checkpoint location, and a live test where pulling the switch stopped the job within one unit of work with a resumable checkpoint and a non-zero exit.\n","# Add a kill switch to a runaway job\n\nA job with no stop button is controlled only by `kill -9`, which leaves work half-applied and state inconsistent. Give the operator a cooperative switch that is polled at safe points, so the job stops after the current unit of work and lands in a resumable state.\n\n## Procedure\n\n1. Define the switch as an out-of-band signal the process can read cheaply: a file, a Redis key, a DB row, or an env var the supervisor can rewrite. File on a shared volume is the simplest:\n       KILL_FILE=\u002Fvar\u002Frun\u002Fbatch\u002Fjob.stop\n       test -f \"$KILL_FILE\" && echo stopping\n\n2. Poll it at a *safe point* — between items, not mid-write. Once per N items and once per outer loop iteration is enough; checking every microsecond wastes the very budget you are protecting:\n       for i, item := range items {\n         if i % 100 == 0 && stopped() { saveCheckpoint(i); return ErrStopped }\n         process(item)\n       }\n\n3. Make the stop idempotent and resumable: persist a checkpoint (`last_processed_id`, offset, cursor) before returning, so a restart continues instead of reprocessing or skipping. Write the checkpoint *after* the side effect commits.\n\n4. Handle `SIGTERM` the same way, so a normal `kubectl delete pod` also stops cleanly. Kubernetes sends `SIGTERM`, waits `terminationGracePeriodSeconds` (default 30), then `SIGKILL`s. Your handler must finish the current unit inside that window:\n       signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)\n       \u002F\u002F set stop flag; do NOT os.Exit mid-write\n\n5. Set the grace window to match: `terminationGracePeriodSeconds: 60` when one unit can take 20 s. A job whose unit of work exceeds the grace window is killed mid-write no matter how good the handler is.\n\n6. Make the switch also pause intake, not just the current worker: a queue consumer should stop pulling new messages (`consumer.pause()`) so stopping does not race a refill.\n\n7. Log the stop with the checkpoint and the count processed, then exit non-zero so the orchestrator records a deliberate stop rather than a success:\n       log.Printf(\"stopped by switch at=%d processed=%d\", i, i)\n\n## Pitfalls\n\n- Checking the switch only at the *end* of the whole job, so it does nothing until the runaway has already finished the damage.\n- Returning immediately without a checkpoint, so the restart reprocesses from zero — or worse, resumes past unprocessed items.\n- `os.Exit(0)` inside the loop, reporting success and skipping deferred cleanup (closing files, releasing locks, flushing).\n- A file switch on a filesystem the worker container does not share, so the operator's `touch` is invisible to the process.\n\n## Verification\n\n    # start the job, let it reach steady state, then pull the switch\n    touch \"$KILL_FILE\"\n    # expect: logs \"stopped by switch at=\u003Cn>\", exit code non-zero, within the grace window\n    ps -o pid,stat,etime -p \"$(pgrep -f batch-job)\"\n    # restart and confirm it resumes from the checkpoint, not from row 0\n    grep checkpoint \u002Fvar\u002Flib\u002Fbatch\u002Fstate.json\n\nReport: the switch mechanism, the poll cadence and checkpoint location, and a live test where pulling the switch stopped the job within one unit of work with a resumable checkpoint and a non-zero exit.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-11 08:47:40",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill add-a-kill-switch-to-a-runaway-job",{"tool":60,"command":61},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill add-a-kill-switch-to-a-runaway-job",{"tool":63,"command":64},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill add-a-kill-switch-to-a-runaway-job","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job\u002FSKILL.md",true,[68,72,78],{"path":69,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"SOURCE.md","REFERENCE","参考文档",360,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job\u002FSOURCE.md",{"path":79,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":80,"sourceHtmlUrl":81},"TRUST.auto.yaml",2211,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-add-a-kill-switch-to-a-runaway-job\u002FTRUST.auto.yaml",[83,111,134,152,165,175],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":87,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":40},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":116,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":40},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[120,121,122,123,124,125,126,127,128,129,130,131,132,133],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":138,"sourceHtmlUrl":139,"categories":140,"keywords":141,"publishedAt":40},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[142,121,143,144,145,146,147,131,130,129,148,149,150,125,151,124,123],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":156,"sourceHtmlUrl":157,"categories":158,"keywords":159,"publishedAt":40},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[160,161,122,162,163,132,130,164,128,127,125,124],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":166,"name":167,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":171,"publishedAt":40},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[172,173,174],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":176,"name":177,"nameZh":6,"description":178,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":179,"sourceHtmlUrl":180,"categories":181,"keywords":182,"publishedAt":40},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[183,184,185,186,187,188,189,34,190,191,192],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]