Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

Commit

Permalink
First release of Sequel driver for River Ruby bindings
Browse files Browse the repository at this point in the history
Related to main `riverqueue` gem's push in [1], this one provides a
driver implementation for the Sequel gem. This is a similar concept to
use the use of `riverpgxv5` in the main Go package -- it breaks up
implementations for specific database packages into separate gems so
that projects using River don't have include every third party database
framework under the sun. I'll also be writing one for ActiveRecord.

Like with [1], functionality for unique jobs and batch inserts is
currently missing, to be added on a follow up release.

[1] riverqueue/riverqueue-ruby#1
  • Loading branch information
brandur committed Nov 20, 2023
1 parent fab399e commit 378bf96
Show file tree
Hide file tree
Showing 11 changed files with 457 additions and 25 deletions.
80 changes: 80 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CI

env:
# Database to connect to that can create other databases with `CREATE DATABASE`.
ADMIN_DATABASE_URL: postgres://postgres:postgres@localhost:5432

# Just a common place for steps to put binaries they need and which is added
# to GITHUB_PATH/PATH.
BIN_PATH: /home/runner/bin

# A suitable URL for a test database.
TEST_DATABASE_URL: postgres://postgres:[email protected]:5432/river_ruby_test?sslmode=disable

on:
- push

jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 3

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Ruby + `bundle install`
uses: ruby/setup-ruby@v1
with:
ruby-version: "head"
bundler-cache: true # runs 'bundle install' and caches installed gems automatically

- name: Standard Ruby
run: bundle exec standardrb

spec:
runs-on: ubuntu-latest
timeout-minutes: 3

services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Ruby + `bundle install`
uses: ruby/setup-ruby@v1
with:
ruby-version: "head"
bundler-cache: true # runs 'bundle install' and caches installed gems automatically

# There is a version of Go on Actions' base image, but it's old and can't
# read modern `go.mod` annotations correctly.
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "stable"
check-latest: true

- name: Create database
run: psql --echo-errors --quiet -c '\timing off' -c "CREATE DATABASE river_ruby_test;" ${ADMIN_DATABASE_URL}

- name: Install River CLI
run: go install github.com/riverqueue/river/cmd/river@latest

- name: river migrate-up
run: river migrate-up --database-url "$TEST_DATABASE_URL"

- name: Rspec
run: bundle exec rspec
16 changes: 14 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
source 'https://rubygems.org'
gemspec
source "https://rubygems.org"

gemspec

group :development, :test do
gem "riverqueue", git: "https://github.com/riverqueue/riverqueue-ruby", branch: "brandur-first-release"
# gem "riverqueue", path: "../riverqueue-ruby"
gem "standard"
end

group :test do
gem "rspec-core"
gem "rspec-expectations"
end
67 changes: 67 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,17 +1,84 @@
GIT
remote: https://github.com/riverqueue/riverqueue-ruby
revision: 802eee2f804826d7bd41b6cef9169a80f5b0be37
branch: brandur-first-release
specs:
riverqueue (0.0.1)

PATH
remote: .
specs:
riverqueue-sequel (0.0.1)
pg
sequel

GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
bigdecimal (3.1.4)
diff-lcs (1.5.0)
json (2.6.3)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
parallel (1.23.0)
parser (3.2.2.4)
ast (~> 2.4.1)
racc
pg (1.5.4)
racc (1.7.3)
rainbow (3.1.1)
regexp_parser (2.8.2)
rexml (3.2.6)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-support (3.12.1)
rubocop (1.57.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-performance (1.19.1)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
ruby-progressbar (1.13.0)
sequel (5.74.0)
bigdecimal
standard (1.32.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.57.2)
standard-custom (~> 1.0.0)
standard-performance (~> 1.2)
standard-custom (1.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.50)
standard-performance (1.2.1)
lint_roller (~> 1.1)
rubocop-performance (~> 1.19.1)
unicode-display_width (2.5.0)

PLATFORMS
arm64-darwin-22
x86_64-linux

DEPENDENCIES
riverqueue!
riverqueue-sequel!
rspec-core
rspec-expectations
standard

BUNDLED WITH
2.4.20
8 changes: 0 additions & 8 deletions README.md

This file was deleted.

23 changes: 23 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# riverqueue-sequel [![Build Status](https://github.com/riverqueue/riverqueue-ruby-sequel/workflows/CI/badge.svg)](https://github.com/riverqueue/riverqueue-ruby-sequel/actions)

[Sequel](https://github.com/jeremyevans/sequel) driver for [River](https://github.com/riverqueue/river)'s [`riverqueue` gem for Ruby](https://rubygems.org/gems/riverqueue).

`Gemfile` should contain the core gem and a driver like this one:

``` yaml
gem "riverqueue"
gem "riverqueue-sequel"
```

Initialize a client with:

```ruby
DB = Sequel.connect("postgres://...")
client = River::Client.new(River::Driver::Sequel.new(DB))
```

See also [`rubyqueue`](https://github.com/riverqueue/riverqueue-ruby).

## Development

See [development](./development.md).
39 changes: 39 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# riverqueue-ruby development

## Install dependencies

```shell
$ bundle install
```
## Run tests

Create a test database and migrate with River's CLI:

```shell
$ go install github.com/riverqueue/river/cmd/river
$ createdb riverqueue_ruby_test
$ river migrate-up --database-url "postgres://localhost/riverqueue_ruby_test"
```

Run all specs:

```shell
$ bundle exec rspec spec
```

## Run lint

```shell
$ standardrb --fix
```

## Publish a new gem

```shell
git checkout master && git pull --rebase
VERSION=v0.0.x
gem build riverqueue-sequel.gemspec
gem push riverqueue-sequel-$VERSION.gem
git tag $VERSION
git push --tags
```
72 changes: 72 additions & 0 deletions lib/driver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
module River::Driver
# Provides a Sequel driver for River.
#
# Used in conjunction with a River client like:
#
# DB = Sequel.connect("postgres://...")
# client = River::Client.new(River::Driver::Sequel.new(DB))
#
class Sequel
def initialize(db)
@db = db

# It's Ruby, so we can only define a model after Sequel's established a
# connection because it's all dynamic.
if !River::Driver::Sequel.const_defined?(:RiverJob)
River::Driver::Sequel.const_set(:RiverJob, Class.new(::Sequel::Model(:river_job)))

# Since we only define our model once, take advantage of knowing this is
# our first initialization to add required extensions.
db.extension(:pg_array)
end
end

def insert(insert_params)
# the call to `#compact` is important so that we remove nils and table
# default values get picked up instead
to_job_row(
RiverJob.create(
{
args: insert_params.encoded_args,
kind: insert_params.kind,
max_attempts: insert_params.max_attempts,
priority: insert_params.priority,
queue: insert_params.queue,
state: insert_params.state,
scheduled_at: insert_params.scheduled_at,
tags: insert_params.tags ? ::Sequel.pg_array(insert_params.tags) : nil
}.compact
)
)
end

private def to_job_row(river_job)
# needs to be accessed through values because Sequel shadows `errors`
errors = river_job.values[:errors]

River::JobRow.new(
id: river_job.id,
attempt: river_job.attempt,
attempted_by: river_job.attempted_by,
created_at: river_job.created_at,
encoded_args: river_job.args,
errors: errors ? JSON.parse(errors, symbolize_names: true).map { |e|
River::AttemptError.new(
at: e[:at],
error: e[:error],
num: e[:num],
trace: e[:trace]
)
} : nil,
finalized_at: river_job.finalized_at,
kind: river_job.kind,
max_attempts: river_job.max_attempts,
priority: river_job.priority,
queue: river_job.queue,
scheduled_at: river_job.scheduled_at,
state: river_job.state,
tags: river_job.tags
)
end
end
end
12 changes: 5 additions & 7 deletions lib/riverqueue-sequel.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
require "sequel"

require_relative "driver"

module River
module Driver
module Sequel
def initialize
end
end
end
end
end
19 changes: 11 additions & 8 deletions riverqueue-sequel.gemspec
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
Gem::Specification.new do |s|
s.name = "riverqueue-sequel"
s.version = "0.0.1"
s.summary = "Sequel driver for the River Ruby gem."
s.name = "riverqueue-sequel"
s.version = "0.0.1"
s.summary = "Sequel driver for the River Ruby gem."
s.description = "Sequel driver for the River Ruby gem."
s.authors = ["Blake Gentry", "Brandur Leach"]
s.email = "[email protected]"
s.files = ["lib/riverqueue-sequel.rb"]
s.homepage = "https://riverqueue.com"
s.license = "LGPL-3.0-or-later"
s.authors = ["Blake Gentry", "Brandur Leach"]
s.email = "[email protected]"
s.files = ["lib/riverqueue-sequel.rb"]
s.homepage = "https://riverqueue.com"
s.license = "LGPL-3.0-or-later"

s.add_dependency "pg"
s.add_dependency "sequel"
end
Loading

0 comments on commit 378bf96

Please sign in to comment.