backburner 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -4
- data/README.md +70 -14
- data/lib/active_job/queue_adapters/backburner_adapter.rb +9 -2
- data/lib/backburner/cli.rb +1 -1
- data/lib/backburner/enqueue_pool.rb +2 -0
- data/lib/backburner/performable.rb +28 -3
- data/lib/backburner/version.rb +1 -1
- data/lib/backburner/worker.rb +38 -4
- data/lib/backburner/workers/threading.rb +16 -0
- data/lib/backburner/workers/threads_on_fork.rb +1 -0
- metadata +8 -82
- data/.github/workflows/ci.yml +0 -45
- data/.github/workflows/github-release.yml +0 -58
- data/.github/workflows/release.yml +0 -221
- data/.gitignore +0 -17
- data/CONTRIBUTING.md +0 -37
- data/Gemfile +0 -7
- data/Rakefile +0 -17
- data/TODO +0 -4
- data/backburner.gemspec +0 -31
- data/examples/custom.rb +0 -25
- data/examples/demo.rb +0 -60
- data/examples/god.rb +0 -46
- data/examples/hooked.rb +0 -87
- data/examples/retried.rb +0 -31
- data/examples/simple.rb +0 -43
- data/examples/stress.rb +0 -31
- data/test/active_job_adapter_test.rb +0 -24
- data/test/async_proxy_test.rb +0 -36
- data/test/back_burner_test.rb +0 -101
- data/test/connection_test.rb +0 -201
- data/test/fixtures/active_job_app.rb +0 -53
- data/test/fixtures/active_jobs.rb +0 -11
- data/test/fixtures/autoload/test_broken_name_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_no_method_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_require_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_runtime_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_syntax_job.rb +0 -4
- data/test/fixtures/autoload/test_broken_timeout_job.rb +0 -4
- data/test/fixtures/autoload/test_same_name_job.rb +0 -5
- data/test/fixtures/hooked.rb +0 -122
- data/test/fixtures/test_fork_jobs.rb +0 -77
- data/test/fixtures/test_forking_jobs.rb +0 -56
- data/test/fixtures/test_jobs.rb +0 -140
- data/test/fixtures/test_queue_settings.rb +0 -54
- data/test/helpers/templogger.rb +0 -22
- data/test/helpers_test.rb +0 -462
- data/test/hooks_test.rb +0 -112
- data/test/job_test.rb +0 -207
- data/test/logger_test.rb +0 -71
- data/test/performable_test.rb +0 -138
- data/test/queue_test.rb +0 -132
- data/test/test_helper.rb +0 -182
- data/test/worker_test.rb +0 -502
- data/test/workers/forking_worker_test.rb +0 -199
- data/test/workers/simple_worker_test.rb +0 -622
- data/test/workers/threading_worker_test.rb +0 -125
- data/test/workers/threads_on_fork_worker_test.rb +0 -751
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Creates the GitHub release page for a tag that already exists, with GitHub's generated notes (merged
|
|
2
|
-
# PRs and new contributors since the previous release) after a link to that version's CHANGELOG.md.
|
|
3
|
-
# release.yml runs it after it publishes; "Run workflow" here (with the tag) creates the page for an
|
|
4
|
-
# earlier release. A tag that already has a release is left alone, so running it twice is harmless.
|
|
5
|
-
# A tag that isn't the newest vX.Y.Z tag is created with --latest=false; the API otherwise marks every
|
|
6
|
-
# new release as Latest.
|
|
7
|
-
|
|
8
|
-
name: github-release
|
|
9
|
-
run-name: github release ${{ inputs.tag }}
|
|
10
|
-
|
|
11
|
-
on:
|
|
12
|
-
workflow_dispatch:
|
|
13
|
-
inputs:
|
|
14
|
-
tag:
|
|
15
|
-
description: 'An existing tag, e.g. v1.2.0'
|
|
16
|
-
required: true
|
|
17
|
-
type: string
|
|
18
|
-
workflow_call:
|
|
19
|
-
inputs:
|
|
20
|
-
tag:
|
|
21
|
-
required: true
|
|
22
|
-
type: string
|
|
23
|
-
|
|
24
|
-
permissions:
|
|
25
|
-
contents: read
|
|
26
|
-
|
|
27
|
-
jobs:
|
|
28
|
-
release-page:
|
|
29
|
-
if: github.repository == 'nesquena/backburner'
|
|
30
|
-
runs-on: ubuntu-latest
|
|
31
|
-
permissions:
|
|
32
|
-
contents: write # creates the release
|
|
33
|
-
steps:
|
|
34
|
-
- name: Create the GitHub release
|
|
35
|
-
shell: bash -eo pipefail {0}
|
|
36
|
-
env:
|
|
37
|
-
TAG: ${{ inputs.tag }}
|
|
38
|
-
CHANGELOG: CHANGELOG.md
|
|
39
|
-
GH_TOKEN: ${{ github.token }}
|
|
40
|
-
run: |
|
|
41
|
-
[[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::'$TAG' is not a tag like v1.2.3"; exit 1; }
|
|
42
|
-
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
43
|
-
echo "$TAG already has a release; leaving it alone"
|
|
44
|
-
exit 0
|
|
45
|
-
fi
|
|
46
|
-
# Compare with the newest vX.Y.Z tag rather than the "Latest" release, so a failed lookup stops the
|
|
47
|
-
# step (pipefail) instead of letting an older tag become Latest
|
|
48
|
-
newest=$(gh api --paginate "repos/$GITHUB_REPOSITORY/git/matching-refs/tags/v" --jq '.[].ref' |
|
|
49
|
-
sed 's#^refs/tags/##' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1)
|
|
50
|
-
flags=()
|
|
51
|
-
if [ "$newest" != "$TAG" ]; then
|
|
52
|
-
echo "$TAG is not the newest tag ($newest): not marking it as latest"
|
|
53
|
-
flags=(--latest=false)
|
|
54
|
-
fi
|
|
55
|
-
# --verify-tag: refuse rather than create the tag. With --generate-notes, GitHub puts these notes
|
|
56
|
-
# before the generated ones.
|
|
57
|
-
gh release create "$TAG" --repo "$GITHUB_REPOSITORY" --verify-tag --title "$TAG" --generate-notes "${flags[@]}" \
|
|
58
|
-
--notes "What changed, and what to do when upgrading: [$CHANGELOG](https://github.com/$GITHUB_REPOSITORY/blob/$TAG/$CHANGELOG)."
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
# Publishes a backburner release to rubygems.org with trusted publishing, gated by the "release"
|
|
2
|
-
# environment: the owner approves each publish.
|
|
3
|
-
#
|
|
4
|
-
# Usual path: merge the release PR (the version in lib/backburner/version.rb and the CHANGELOG.md
|
|
5
|
-
# heading stamped with the date, e.g. "## Version 1.8.0 (Nov 1 2026)"), then "Run workflow" on master
|
|
6
|
-
# with the version. build checks the version, that the changelog's first heading is that version with
|
|
7
|
-
# a date, and the branch, and builds the gem reproducibly; publish waits for approval, pushes the gem
|
|
8
|
-
# with short-lived trusted-publishing credentials, then creates the tag vX.Y.Z on the built commit.
|
|
9
|
-
# Pushing a vX.Y.Z tag on a master commit runs the same checks. "Re-run failed jobs" (not "Re-run all
|
|
10
|
-
# jobs", which rebuilds) resumes a release that stopped partway.
|
|
11
|
-
# If the gem is pushed but the tag step keeps failing, push the tag by hand at the built commit: that
|
|
12
|
-
# tag push's run skips the push (same sum).
|
|
13
|
-
# Then github-release.yml creates the GitHub release page for the tag (it can also be run by hand for
|
|
14
|
-
# an earlier tag).
|
|
15
|
-
#
|
|
16
|
-
# Dry run: tick dry_run to check the wiring. Everything runs except the changelog checks, the tag, the
|
|
17
|
-
# push and the release page; the credential exchange fails unless the trusted publisher is set up.
|
|
18
|
-
#
|
|
19
|
-
# The "release" environment's protection rules are the ONLY gate on publishing (required reviewer, no
|
|
20
|
-
# admin bypass, deployments only from master and v*.*.* tags): RubyGems trusts any run of this file
|
|
21
|
-
# that uses that environment, and a branch or tag can carry its own modified copy of it. The trusted
|
|
22
|
-
# publisher on rubygems.org must name the environment. Before approving a deployment, check
|
|
23
|
-
# who started the run, the event, that the commit is the release PR's merge commit, and the build
|
|
24
|
-
# log's "is on master" line. Reject any run you won't approve: a waiting run blocks the next one.
|
|
25
|
-
# A deployment rule for X.Y-stable lets anyone with write access create such a branch carrying its own
|
|
26
|
-
# copy of this file: add one only for a maintenance release, and remove it after.
|
|
27
|
-
|
|
28
|
-
name: release
|
|
29
|
-
run-name: release ${{ inputs.version || github.ref_name }}${{ inputs.dry_run && ' (dry run)' || '' }}
|
|
30
|
-
|
|
31
|
-
on:
|
|
32
|
-
push:
|
|
33
|
-
tags: ['v[0-9]+.[0-9]+.[0-9]+']
|
|
34
|
-
workflow_dispatch:
|
|
35
|
-
inputs:
|
|
36
|
-
version:
|
|
37
|
-
description: 'Version to release (already in the version file of this branch), e.g. 1.2.0'
|
|
38
|
-
required: true
|
|
39
|
-
type: string
|
|
40
|
-
dry_run:
|
|
41
|
-
description: 'Dry run: check, build and exchange credentials, but create no tag and push nothing'
|
|
42
|
-
required: false
|
|
43
|
-
type: boolean
|
|
44
|
-
default: false
|
|
45
|
-
|
|
46
|
-
permissions:
|
|
47
|
-
contents: read
|
|
48
|
-
|
|
49
|
-
concurrency:
|
|
50
|
-
group: release
|
|
51
|
-
cancel-in-progress: false
|
|
52
|
-
|
|
53
|
-
jobs:
|
|
54
|
-
build:
|
|
55
|
-
if: github.repository == 'nesquena/backburner'
|
|
56
|
-
runs-on: ubuntu-latest
|
|
57
|
-
env:
|
|
58
|
-
TRUNK: master
|
|
59
|
-
TAG_PREFIX: v
|
|
60
|
-
GEMS: 'backburner:.'
|
|
61
|
-
VERSION_FILE: lib/backburner/version.rb
|
|
62
|
-
CHANGELOG: CHANGELOG.md
|
|
63
|
-
CHANGELOG_HEADING: '^## '
|
|
64
|
-
CHANGELOG_TOP: '^## Version ([0-9]+\.[0-9]+\.[0-9]+)( |$)'
|
|
65
|
-
outputs:
|
|
66
|
-
version: ${{ steps.check.outputs.version }}
|
|
67
|
-
tag: ${{ steps.check.outputs.tag }}
|
|
68
|
-
steps:
|
|
69
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
70
|
-
with:
|
|
71
|
-
fetch-depth: 0
|
|
72
|
-
submodules: true
|
|
73
|
-
persist-credentials: false
|
|
74
|
-
- uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0
|
|
75
|
-
with:
|
|
76
|
-
ruby-version: '3.3'
|
|
77
|
-
- name: Check the version
|
|
78
|
-
id: check
|
|
79
|
-
shell: bash -eo pipefail {0}
|
|
80
|
-
env:
|
|
81
|
-
INPUT_VERSION: ${{ inputs.version }}
|
|
82
|
-
DRY_RUN: ${{ inputs.dry_run }}
|
|
83
|
-
run: |
|
|
84
|
-
if [ "$GITHUB_EVENT_NAME" = workflow_dispatch ]; then
|
|
85
|
-
version="$INPUT_VERSION"
|
|
86
|
-
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::the version input is not a plain version like 1.2.3"; exit 1; }
|
|
87
|
-
case "$GITHUB_REF" in
|
|
88
|
-
"refs/heads/$TRUNK"|"refs/heads/${version%.*}-stable") ;;
|
|
89
|
-
*) echo "::error::run this on $TRUNK or ${version%.*}-stable, not $GITHUB_REF"; exit 1 ;;
|
|
90
|
-
esac
|
|
91
|
-
tag="$TAG_PREFIX$version"
|
|
92
|
-
tagged=$(git ls-remote origin "refs/tags/$tag*" | awk -v t="refs/tags/$tag" '$2 == t || $2 == t "^{}" { print $1 }')
|
|
93
|
-
[ -z "$tagged" ] || echo "$tagged" | grep -qx "$GITHUB_SHA" ||
|
|
94
|
-
{ echo "::error::tag $tag already exists at another commit"; exit 1; }
|
|
95
|
-
else
|
|
96
|
-
tag="$GITHUB_REF_NAME"
|
|
97
|
-
version="${tag#"$TAG_PREFIX"}"
|
|
98
|
-
[[ "$tag" == "$TAG_PREFIX"* && "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "::error::tag $tag is not ${TAG_PREFIX}X.Y.Z"; exit 1; }
|
|
99
|
-
fi
|
|
100
|
-
file_version=$(ruby -e 'puts File.binread(ENV["VERSION_FILE"])[/\bVERSION\s*=\s*["\x27]([^"\x27]+)/, 1]')
|
|
101
|
-
[ "$version" = "$file_version" ] || { echo "::error::version $version but $VERSION_FILE says $file_version"; exit 1; }
|
|
102
|
-
if [ "$DRY_RUN" = true ]; then
|
|
103
|
-
echo "::warning::dry run: not checking $CHANGELOG"
|
|
104
|
-
else
|
|
105
|
-
heading=$(grep -m1 -E "$CHANGELOG_HEADING" "$CHANGELOG") || { echo "::error::$CHANGELOG has no heading matching '$CHANGELOG_HEADING'"; exit 1; }
|
|
106
|
-
top=$(echo "$heading" | sed -nE "s/$CHANGELOG_TOP.*/\1/p")
|
|
107
|
-
[ "$top" = "$version" ] || { echo "::error::$CHANGELOG starts with '$heading', not release $version: merge the release PR first, and nothing after it"; exit 1; }
|
|
108
|
-
rest="${heading#*"$version"}"
|
|
109
|
-
[[ "$rest" =~ (19|20)[0-9][0-9] ]] && ! echo "$rest" | grep -qiwE 'unreleased|tbd|tba' ||
|
|
110
|
-
{ echo "::error::$CHANGELOG's '$heading' isn't stamped with a date yet"; exit 1; }
|
|
111
|
-
fi
|
|
112
|
-
series="${version%.*}-stable"
|
|
113
|
-
on=""
|
|
114
|
-
for b in "$series" "$TRUNK"; do
|
|
115
|
-
git merge-base --is-ancestor "$GITHUB_SHA" "refs/remotes/origin/$b" 2>/dev/null && on="$b"
|
|
116
|
-
done
|
|
117
|
-
[ -n "$on" ] || { echo "::error::$version ($GITHUB_SHA) is not on $TRUNK or $series"; exit 1; }
|
|
118
|
-
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
119
|
-
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
120
|
-
echo "$version ($GITHUB_SHA) is on $on"
|
|
121
|
-
- name: Build the gems
|
|
122
|
-
shell: bash -eo pipefail {0}
|
|
123
|
-
env:
|
|
124
|
-
VERSION: ${{ steps.check.outputs.version }}
|
|
125
|
-
run: |
|
|
126
|
-
SOURCE_DATE_EPOCH=$(git log -1 --format=%ct "$GITHUB_SHA"); export SOURCE_DATE_EPOCH
|
|
127
|
-
mkdir dist
|
|
128
|
-
for spec in $GEMS; do
|
|
129
|
-
g="${spec%%:*}"; dir="${spec#*:}"; [ "$dir" = "$spec" ] && dir=.
|
|
130
|
-
out="$GITHUB_WORKSPACE/dist/$g-$VERSION.gem"
|
|
131
|
-
(cd "$dir" && gem build "$g.gemspec" --output "$out")
|
|
132
|
-
[ "$(gem spec "$out" name)" = "--- $g" ] && [ "$(gem spec "$out" version | sed -n 's/^version: //p')" = "$VERSION" ] ||
|
|
133
|
-
{ echo "::error::$out is not $g $VERSION:"; gem spec "$out" name; gem spec "$out" version; exit 1; }
|
|
134
|
-
echo "$g" >> dist/ORDER
|
|
135
|
-
done
|
|
136
|
-
echo "SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH (ruby $(ruby -e 'print RUBY_VERSION'), rubygems $(gem -v))"
|
|
137
|
-
(cd dist && sha256sum *.gem > SHA256SUMS && cat ORDER SHA256SUMS)
|
|
138
|
-
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
139
|
-
with:
|
|
140
|
-
name: gems-${{ steps.check.outputs.version }}
|
|
141
|
-
path: dist/
|
|
142
|
-
if-no-files-found: error
|
|
143
|
-
|
|
144
|
-
publish:
|
|
145
|
-
needs: build
|
|
146
|
-
runs-on: ubuntu-latest
|
|
147
|
-
environment: release
|
|
148
|
-
permissions:
|
|
149
|
-
contents: write # creates the tag on a dispatched release
|
|
150
|
-
id-token: write # the RubyGems trusted-publishing exchange
|
|
151
|
-
steps:
|
|
152
|
-
- name: Refuse a stale run (the tag is somewhere else)
|
|
153
|
-
shell: bash -eo pipefail {0}
|
|
154
|
-
env:
|
|
155
|
-
TAG: ${{ needs.build.outputs.tag }}
|
|
156
|
-
run: |
|
|
157
|
-
tagged=$(git ls-remote "https://github.com/$GITHUB_REPOSITORY" "refs/tags/$TAG*" |
|
|
158
|
-
awk -v t="refs/tags/$TAG" '$2 == t || $2 == t "^{}" { print $1 }')
|
|
159
|
-
if [ -z "$tagged" ] && [ "$GITHUB_EVENT_NAME" = workflow_dispatch ]; then
|
|
160
|
-
echo "tag $TAG will be created at $GITHUB_SHA"
|
|
161
|
-
else
|
|
162
|
-
echo "$tagged" | grep -qx "$GITHUB_SHA" || { echo "::error::tag $TAG is not at $GITHUB_SHA (now: ${tagged:-gone}); this run is stale"; exit 1; }
|
|
163
|
-
fi
|
|
164
|
-
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
165
|
-
with:
|
|
166
|
-
name: gems-${{ needs.build.outputs.version }}
|
|
167
|
-
path: dist
|
|
168
|
-
- name: Check the sums
|
|
169
|
-
working-directory: dist
|
|
170
|
-
run: sha256sum -c SHA256SUMS
|
|
171
|
-
- uses: ruby/setup-ruby@de492cf36cbab201753d720ce4f4e336cd688c94 # v1.336.0
|
|
172
|
-
with:
|
|
173
|
-
ruby-version: '3.3'
|
|
174
|
-
- uses: rubygems/configure-rubygems-credentials@dc5a8d8553e6ee01fc26761a49e99e733d17954a # v2.1.0
|
|
175
|
-
- name: Dry run ends here
|
|
176
|
-
if: inputs.dry_run
|
|
177
|
-
run: echo "Credentials exchange succeeded, so the trusted publisher works. No tag created, nothing pushed."
|
|
178
|
-
- name: Push the gems
|
|
179
|
-
if: ${{ !inputs.dry_run }}
|
|
180
|
-
shell: bash -eo pipefail {0}
|
|
181
|
-
working-directory: dist
|
|
182
|
-
env:
|
|
183
|
-
VERSION: ${{ needs.build.outputs.version }}
|
|
184
|
-
run: |
|
|
185
|
-
while read -r g; do
|
|
186
|
-
sum=$(sha256sum "$g-$VERSION.gem" | cut -d' ' -f1)
|
|
187
|
-
published=$(curl -fsS "https://rubygems.org/api/v1/versions/$g.json" 2>/dev/null |
|
|
188
|
-
ruby -rjson -e 'b = $stdin.read; v = (b.empty? ? [] : JSON.parse(b)).find { |x| x["number"] == ENV["VERSION"] && x["platform"] == "ruby" }; print v ? v["sha"].to_s : ""' || true)
|
|
189
|
-
if [ -z "$published" ]; then
|
|
190
|
-
gem push "$g-$VERSION.gem" </dev/null
|
|
191
|
-
elif [ "$published" = "$sum" ]; then
|
|
192
|
-
echo "$g $VERSION is already on rubygems.org with this sum; skipping"
|
|
193
|
-
else
|
|
194
|
-
echo "::error::$g $VERSION is already on rubygems.org with sha256 $published, not this build's $sum"; exit 1
|
|
195
|
-
fi
|
|
196
|
-
done < ORDER
|
|
197
|
-
- name: Create the tag
|
|
198
|
-
if: github.event_name == 'workflow_dispatch' && !inputs.dry_run
|
|
199
|
-
shell: bash -eo pipefail {0}
|
|
200
|
-
env:
|
|
201
|
-
TAG: ${{ needs.build.outputs.tag }}
|
|
202
|
-
GH_TOKEN: ${{ github.token }}
|
|
203
|
-
run: |
|
|
204
|
-
tagged=$(git ls-remote "https://github.com/$GITHUB_REPOSITORY" "refs/tags/$TAG*" |
|
|
205
|
-
awk -v t="refs/tags/$TAG" '$2 == t || $2 == t "^{}" { print $1 }')
|
|
206
|
-
if [ -z "$tagged" ]; then
|
|
207
|
-
gh api "repos/$GITHUB_REPOSITORY/git/refs" -f ref="refs/tags/$TAG" -f sha="$GITHUB_SHA"
|
|
208
|
-
elif echo "$tagged" | grep -qx "$GITHUB_SHA"; then
|
|
209
|
-
echo "tag $TAG is already at $GITHUB_SHA"
|
|
210
|
-
else
|
|
211
|
-
echo "::error::tag $TAG is not at $GITHUB_SHA (now: $tagged)"; exit 1
|
|
212
|
-
fi
|
|
213
|
-
|
|
214
|
-
release-page:
|
|
215
|
-
needs: [build, publish]
|
|
216
|
-
if: ${{ !inputs.dry_run }}
|
|
217
|
-
permissions:
|
|
218
|
-
contents: write # github-release.yml creates the release
|
|
219
|
-
uses: ./.github/workflows/github-release.yml
|
|
220
|
-
with:
|
|
221
|
-
tag: ${{ needs.build.outputs.tag }}
|
data/.gitignore
DELETED
data/CONTRIBUTING.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
We love pull requests. Here's a quick guide:
|
|
2
|
-
|
|
3
|
-
1. Fork the repo.
|
|
4
|
-
|
|
5
|
-
2. Run the tests. We only take pull requests with passing tests, and it's great
|
|
6
|
-
to know that you have a clean slate: `bundle && rake test`
|
|
7
|
-
|
|
8
|
-
3. Add a test for your change. Only refactoring and documentation changes
|
|
9
|
-
require no new tests. If you are adding functionality or fixing a bug, we need
|
|
10
|
-
a test!
|
|
11
|
-
|
|
12
|
-
4. Make the test pass.
|
|
13
|
-
|
|
14
|
-
5. Push to your fork and submit a pull request.
|
|
15
|
-
|
|
16
|
-
At this point you're waiting on us. We like to at least comment on, if not
|
|
17
|
-
accept, pull requests within three business days (and, typically, one business
|
|
18
|
-
day). We may suggest some changes or improvements or alternatives.
|
|
19
|
-
|
|
20
|
-
Some things that will increase the chance that your pull request is accepted:
|
|
21
|
-
|
|
22
|
-
* Use Rails idioms and helpers
|
|
23
|
-
* Include tests that fail without your code, and pass with it
|
|
24
|
-
* Update the documentation and README for anything affected by your contribution
|
|
25
|
-
|
|
26
|
-
Syntax:
|
|
27
|
-
|
|
28
|
-
* Two spaces, no tabs.
|
|
29
|
-
* No trailing whitespace. Blank lines should not have any space.
|
|
30
|
-
* Prefer &&/|| over and/or.
|
|
31
|
-
* MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
|
32
|
-
* a = b and not a=b.
|
|
33
|
-
* Follow the conventions you see used in the source already.
|
|
34
|
-
|
|
35
|
-
And in case we didn't emphasize it enough: we love tests!
|
|
36
|
-
|
|
37
|
-
NOTE: Adapted from https://raw.github.com/thoughtbot/factory_girl_rails/master/CONTRIBUTING.md
|
data/Gemfile
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
source 'https://rubygems.org'
|
|
2
|
-
|
|
3
|
-
# Specify your gem's dependencies in backburner.gemspec
|
|
4
|
-
gemspec
|
|
5
|
-
|
|
6
|
-
# Test against an older Active Job (and the Active Support it needs), as CI does: ACTIVEJOB_VERSION=7.1 bundle install
|
|
7
|
-
gem 'activejob', "~> #{ENV['ACTIVEJOB_VERSION']}.0" unless ENV['ACTIVEJOB_VERSION'].to_s.empty?
|
data/Rakefile
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env rake
|
|
2
|
-
require "bundler/gem_tasks"
|
|
3
|
-
require 'rake/testtask'
|
|
4
|
-
# require 'yard'
|
|
5
|
-
|
|
6
|
-
task :test do
|
|
7
|
-
Rake::TestTask.new do |t|
|
|
8
|
-
t.libs.push "lib"
|
|
9
|
-
t.test_files = FileList[File.expand_path('../test/**/*_test.rb', __FILE__)]
|
|
10
|
-
t.verbose = true
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
task :default => :test
|
|
15
|
-
|
|
16
|
-
# task :doc do
|
|
17
|
-
# YARD::CLI::Yardoc.new.run
|
data/TODO
DELETED
data/backburner.gemspec
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
require File.expand_path('../lib/backburner/version', __FILE__)
|
|
3
|
-
|
|
4
|
-
Gem::Specification.new do |s|
|
|
5
|
-
s.authors = ["Nathan Esquenazi"]
|
|
6
|
-
s.email = ["nesquena@gmail.com"]
|
|
7
|
-
s.description = %q{Beanstalk background job processing made easy}
|
|
8
|
-
s.summary = %q{Reliable beanstalk background job processing made easy for Ruby and Sinatra}
|
|
9
|
-
s.homepage = "http://github.com/nesquena/backburner"
|
|
10
|
-
|
|
11
|
-
s.files = `git ls-files`.split($\)
|
|
12
|
-
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
|
13
|
-
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
14
|
-
s.name = "backburner"
|
|
15
|
-
s.require_paths = ["lib"]
|
|
16
|
-
s.version = Backburner::VERSION
|
|
17
|
-
s.license = 'MIT'
|
|
18
|
-
s.required_ruby_version = '>= 2.7'
|
|
19
|
-
|
|
20
|
-
s.add_runtime_dependency 'beaneater', '~> 1.0'
|
|
21
|
-
s.add_runtime_dependency 'dante', '> 0.1.5'
|
|
22
|
-
s.add_runtime_dependency 'concurrent-ruby', '~> 1.0', '>= 1.0.1'
|
|
23
|
-
s.add_runtime_dependency 'logger' # a bundled gem (no longer a default one) since Ruby 4.0
|
|
24
|
-
|
|
25
|
-
s.add_development_dependency 'rake'
|
|
26
|
-
s.add_development_dependency 'minitest', '5.1.0'
|
|
27
|
-
s.add_development_dependency 'mutex_m' # minitest 5.1.0 requires it; a bundled gem (not a default one) since Ruby 3.4
|
|
28
|
-
s.add_development_dependency 'mocha'
|
|
29
|
-
s.add_development_dependency 'activejob', '>= 6.0'
|
|
30
|
-
s.add_development_dependency 'activesupport', '>= 6.0'
|
|
31
|
-
end
|
data/examples/custom.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
$:.unshift "lib"
|
|
2
|
-
require 'backburner'
|
|
3
|
-
|
|
4
|
-
# Define ruby job
|
|
5
|
-
class TestJob
|
|
6
|
-
include Backburner::Queue
|
|
7
|
-
# queue "test-job"
|
|
8
|
-
|
|
9
|
-
def self.perform(value, user)
|
|
10
|
-
puts "[TestJob] Running perform with args: [#{value}, #{user}]"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Configure Backburner
|
|
15
|
-
Backburner.configure do |config|
|
|
16
|
-
config.beanstalk_url = "beanstalk://127.0.0.1"
|
|
17
|
-
config.tube_namespace = "demo.production"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Enqueue tasks
|
|
21
|
-
Backburner.enqueue TestJob, 5, 3
|
|
22
|
-
Backburner.enqueue TestJob, 10, 6
|
|
23
|
-
|
|
24
|
-
# Work tasks using threaded worker
|
|
25
|
-
Backburner.work("test-job", :worker => Backburner::Workers::ThreadsOnFork)
|
data/examples/demo.rb
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
$:.unshift "lib"
|
|
2
|
-
require 'backburner'
|
|
3
|
-
|
|
4
|
-
module Tester
|
|
5
|
-
class TestJob
|
|
6
|
-
include Backburner::Queue
|
|
7
|
-
queue "test.job"
|
|
8
|
-
|
|
9
|
-
def self.perform(value, user)
|
|
10
|
-
p [value, user]
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
class UserModel
|
|
15
|
-
include Backburner::Performable
|
|
16
|
-
|
|
17
|
-
attr_accessor :id, :name
|
|
18
|
-
|
|
19
|
-
def self.first
|
|
20
|
-
self.find(3, "John")
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.find(id, name="Fetched")
|
|
24
|
-
self.new(id, name)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def initialize(id, name)
|
|
28
|
-
@id, @name = id, name
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def hello(x, y)
|
|
32
|
-
puts "Instance #{x} and #{y} and my id is #{id}"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def self.foo(x, y)
|
|
36
|
-
puts "Class #{x} and #{y}"
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# connection = Backburner::Connection.new("beanstalk://127.0.0.1")
|
|
42
|
-
|
|
43
|
-
Backburner.configure do |config|
|
|
44
|
-
config.beanstalk_url = "beanstalk://127.0.0.1"
|
|
45
|
-
config.tube_namespace = "myblog.production"
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# p Backburner.configuration.beanstalk_url
|
|
49
|
-
# p Backburner::Worker.connection
|
|
50
|
-
|
|
51
|
-
Backburner.enqueue Tester::TestJob, 5, 3
|
|
52
|
-
Backburner.enqueue Tester::TestJob, 10, 6
|
|
53
|
-
@user = Tester::UserModel.first
|
|
54
|
-
@user.async.hello("foo", "bar")
|
|
55
|
-
Tester::UserModel.async.foo("bar", "baz")
|
|
56
|
-
|
|
57
|
-
Backburner.default_queues.concat([Tester::TestJob.queue, Tester::UserModel.queue])
|
|
58
|
-
Backburner.work
|
|
59
|
-
# Backburner.work("test.job")
|
|
60
|
-
# Backburner.work("tester/user-model")
|
data/examples/god.rb
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
God.watch do |w|
|
|
2
|
-
w.name = "backburner-worker-1"
|
|
3
|
-
w.dir = '/path/to/app/dir'
|
|
4
|
-
w.env = { 'PADRINO_ENV' => 'production', 'QUEUES' => 'newsletter-sender,push-message' }
|
|
5
|
-
w.group = 'backburner-workers'
|
|
6
|
-
w.interval = 30.seconds
|
|
7
|
-
w.start = "bundle exec rake -f Rakefile backburner:work"
|
|
8
|
-
w.log = "/var/log/god/backburner-worker-1.log"
|
|
9
|
-
|
|
10
|
-
# restart if memory gets too high
|
|
11
|
-
w.transition(:up, :restart) do |on|
|
|
12
|
-
on.condition(:memory_usage) do |c|
|
|
13
|
-
c.above = 50.megabytes
|
|
14
|
-
c.times = 3
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# determine the state on startup
|
|
19
|
-
w.transition(:init, { true => :up, false => :start }) do |on|
|
|
20
|
-
on.condition(:process_running) do |c|
|
|
21
|
-
c.running = true
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# determine when process has finished starting
|
|
26
|
-
w.transition([:start, :restart], :up) do |on|
|
|
27
|
-
on.condition(:process_running) do |c|
|
|
28
|
-
c.running = true
|
|
29
|
-
c.interval = 5.seconds
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# failsafe
|
|
33
|
-
on.condition(:tries) do |c|
|
|
34
|
-
c.times = 5
|
|
35
|
-
c.transition = :start
|
|
36
|
-
c.interval = 5.seconds
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# start if process is not running
|
|
41
|
-
w.transition(:up, :start) do |on|
|
|
42
|
-
on.condition(:process_running) do |c|
|
|
43
|
-
c.running = false
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
data/examples/hooked.rb
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
$:.unshift "lib"
|
|
2
|
-
require 'backburner'
|
|
3
|
-
|
|
4
|
-
$fail = 0
|
|
5
|
-
class User
|
|
6
|
-
include Backburner::Performable
|
|
7
|
-
|
|
8
|
-
# Called with the job args before a job is placed on the queue.
|
|
9
|
-
# !! If the hook returns `false`, the job will not be placed on the queue.
|
|
10
|
-
def self.before_enqueue_foo(*args)
|
|
11
|
-
puts "[before_enqueue] Just about to enqueue #{self} with #{args.inspect}"
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Called with the job args after a job is placed on the queue.
|
|
15
|
-
# !! Any exception raised propagates up to the code which queued the job.
|
|
16
|
-
def self.after_enqueue_foo(*args)
|
|
17
|
-
puts "[after_enqueue] Finished enqueuing #{self} with #{args.inspect}"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Called with the job args before perform. If it raises
|
|
21
|
-
# `Backburner::Job::DontPerform`, the job is aborted. Other exceptions
|
|
22
|
-
# are treated like regular job exceptions.
|
|
23
|
-
def self.before_perform_foo(*args)
|
|
24
|
-
puts "[before_perform] Just about to perform #{self} with #{args.inspect}"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Called with the job args after it performs. Uncaught
|
|
28
|
-
# exceptions will be treated like regular job exceptions.
|
|
29
|
-
def self.after_perform_foo(*args)
|
|
30
|
-
puts "[after_perform] Just finished performing #{self} with #{args.inspect}"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Called with the job args. It is expected to yield in order
|
|
34
|
-
# to perform the job (but is not required to do so). It may handle exceptions
|
|
35
|
-
# thrown by perform, but uncaught exceptions will be treated like regular job exceptions.
|
|
36
|
-
def self.around_perform_bar(*args)
|
|
37
|
-
puts "[around_perform_bar before] About to perform #{self} with #{args.inspect}"
|
|
38
|
-
yield
|
|
39
|
-
puts "[around_perform_bar after] Just after performing #{self} with #{args.inspect}"
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Called with the job args. It is expected to yield in order
|
|
43
|
-
# to perform the job (but is not required to do so). It may handle exceptions
|
|
44
|
-
# thrown by perform, but uncaught exceptions will be treated like regular job exceptions.
|
|
45
|
-
def self.around_perform_cat(*args)
|
|
46
|
-
puts "[around_perform_cat before] About to perform #{self} with #{args.inspect}"
|
|
47
|
-
yield
|
|
48
|
-
puts "[around_perform_cat after] Just after performing #{self} with #{args.inspect}"
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Called with the job args. It is expected to yield in order
|
|
52
|
-
# to perform the job (but is not required to do so). It may handle exceptions
|
|
53
|
-
# thrown by perform, but uncaught exceptions will be treated like regular job exceptions.
|
|
54
|
-
def self.around_perform_foo(*args)
|
|
55
|
-
puts "[around_perform_foo before] About to perform #{self} with #{args.inspect}"
|
|
56
|
-
yield
|
|
57
|
-
puts "[around_perform_foo after] Just after performing #{self} with #{args.inspect}"
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Called with the exception and job args if any exception occurs
|
|
61
|
-
# while performing the job (or hooks).
|
|
62
|
-
def self.on_failure_foo(ex, *args)
|
|
63
|
-
puts "[on_failure] Failure #{ex.inspect} occurred for job #{self} with #{args.inspect}"
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def self.foo
|
|
67
|
-
$fail += 1
|
|
68
|
-
raise "Fail!" if $fail == 1
|
|
69
|
-
puts "This is the job running successfully!!"
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# Configure Backburner
|
|
74
|
-
Backburner.configure do |config|
|
|
75
|
-
config.beanstalk_url = "beanstalk://127.0.0.1"
|
|
76
|
-
config.tube_namespace = "demo.production"
|
|
77
|
-
config.on_error = lambda { |e| puts "HEY!!! #{e.class}" }
|
|
78
|
-
config.max_job_retries = 1
|
|
79
|
-
config.retry_delay = 0
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Enqueue tasks
|
|
83
|
-
User.async.foo
|
|
84
|
-
|
|
85
|
-
# Run work
|
|
86
|
-
# Backburner.default_queues << "user"
|
|
87
|
-
Backburner.work
|
data/examples/retried.rb
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
$:.unshift "lib"
|
|
2
|
-
require 'backburner'
|
|
3
|
-
|
|
4
|
-
$error = 0
|
|
5
|
-
|
|
6
|
-
class User
|
|
7
|
-
include Backburner::Performable
|
|
8
|
-
attr_accessor :id, :name
|
|
9
|
-
|
|
10
|
-
def self.foo(x, y)
|
|
11
|
-
$error += 1
|
|
12
|
-
raise "fail #{$error}" unless $error > 3
|
|
13
|
-
puts "User #foo args [#{x}, #{y}] Success!!"
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Configure Backburner
|
|
18
|
-
Backburner.configure do |config|
|
|
19
|
-
config.beanstalk_url = "beanstalk://127.0.0.1"
|
|
20
|
-
config.tube_namespace = "demo.production"
|
|
21
|
-
config.on_error = lambda { |e| puts "HEY!!! #{e.class}" }
|
|
22
|
-
config.max_job_retries = 3
|
|
23
|
-
config.retry_delay = 0
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Enqueue tasks
|
|
27
|
-
User.async(:queue => "retried").foo("bar", "baz")
|
|
28
|
-
|
|
29
|
-
# Run work
|
|
30
|
-
# Backburner.default_queues << "user"
|
|
31
|
-
Backburner.work
|