{"adoption": {"forks": 60, "observed_at": "2026-08-28T04:04:20.324233+00:00", "stars": 1313}, "canonical_url": "https://ross.abutalabs.com/products/job-iteration", "card": {"archived": false, "artifact_type": "library", "description": "Makes your background jobs interruptible and resumable by design.", "domain": ["backend", "web-development", "microservices"], "enriched": true, "function": ["concurrency", "workflow-automation", "developer-tools"], "health_score": 97, "homepage": "https://www.rubydoc.info/gems/job-iteration", "language": "Ruby", "license": "MIT", "license_family": "permissive", "maturity": "stable", "member_repos": ["Shopify/job-iteration"], "name": "Shopify/job-iteration", "platform": ["ruby", "cloud"], "pushed_at": "2026-08-11T10:03:17+00:00", "repo": "Shopify/job-iteration", "stars": 1313, "tags": ["activejob", "background-jobs", "resumable-jobs", "checkpointing", "rails", "long-running-jobs", "job-processing", "automation", "web-server"], "topics": [], "urls": [], "use_cases": ["resume background jobs after deploys or restarts", "process millions of ActiveRecord records in a job without losing progress", "make long-running ActiveJob jobs interruptible and resumable", "safely handle worker restarts and pod evictions during batch processing", "checkpoint job progress when iterating over database relations", "backfill or migrate large datasets in background jobs"], "what_it_is": "A Ruby gem extending ActiveJob that makes long-running background jobs interruptible and resumable via cursor-based checkpointing. Developed at Shopify, it lets jobs safely survive deploys, worker restarts, and infrastructure disruptions without losing progress.", "when_to_avoid": ["your jobs are short-lived and rarely interrupted", "you don't use Rails ActiveJob or a Ruby backend", "you need a general-purpose job scheduler or queue rather than an iteration extension"], "when_to_choose": ["you run long-running background jobs on Rails/ActiveJob that risk being interrupted by deploys or infrastructure restarts", "you need resumable iteration over large ActiveRecord relations or batches", "you operate in cloud environments where workers can be evicted at any time"]}, "data_as_of": "2026-08-30T08:39:29.467469+00:00", "members": [{"path": "/products/job-iteration", "repo": "Shopify/job-iteration", "role": "main", "score": 89}], "provenance": {"archived": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "artifact_type": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "description": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "domain": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "enriched": {"inputs": [], "kind": "computed", "method": "enrichment_status"}, "function": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "health_score": {"inputs": ["days_since_push", "days_since_release", "archived"], "kind": "computed", "method": "health_v1"}, "homepage": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "language": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "license": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "license_family": {"inputs": ["license"], "kind": "computed", "method": "license_family"}, "maturity": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "member_repos": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "name": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "platform": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "pushed_at": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "repo": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "stars": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "tags": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "topics": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "urls": {"kind": "observed", "observed_at": "2026-08-28T04:04:20.324233+00:00", "source": "github"}, "use_cases": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "what_it_is": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "when_to_avoid": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}, "when_to_choose": {"confidence": null, "enriched_at": "2026-08-30T04:48:49.349493+00:00", "kind": "inferred", "prompt_version": 1, "sources": [{"content_hash": "df8e6c3cfe4c829353bda1acb1bd5b4d0ef5392af700cf9151132e9c519f989b", "fetched_at": "2026-08-28T04:04:20.324233+00:00", "kind": "readme", "missing": false, "url": "https://github.com/Shopify/job-iteration"}, {"content_hash": "36809a830d251a6bd343ad367a04222c77969c70068db0136142564d09ce15a0", "fetched_at": "2026-08-29T12:07:23.433349+00:00", "kind": "homepage", "missing": false, "url": "https://www.rubydoc.info/gems/job-iteration"}], "taxonomy_version": 1}}, "score": {"components": {"activity": 97, "longevity": 100, "rhythm": 72}, "computed_at": "2026-09-03T02:20:16.233290+00:00", "flags": [], "formula": "round(0.45*activity + 0.35*rhythm + 0.20*longevity); archived -> min(score, 10)", "inputs": {"age_days": 3003, "days_push": 22, "days_rel": 111, "gap_med": 55, "n_releases_24m": 10}, "score": 89, "version": 2}, "staleness": {"enrichment_outdated": false, "low_confidence": false, "scrape_days": 9, "stale_scrape": false}}