Skip to content

Commit

Permalink
Add sample app for Shoryuken
Browse files Browse the repository at this point in the history
This is able to enqueue jobs and process them, sending reports to
requestcatcher, but the web process does not know about the queues, need
to look into it some more.
  • Loading branch information
carlosantoniodasilva committed Apr 30, 2024
1 parent 597b7c5 commit 8cfe5ec
Show file tree
Hide file tree
Showing 28 changed files with 676 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
/log/
/judoscale-*/Gemfile*.lock
*.gem
.env*
19 changes: 19 additions & 0 deletions sample-apps/shoryuken-sample/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

# Require only the frameworks we currently use instead of loading everything.
%w(actionpack actionview activejob railties).each { |rails_gem|
gem rails_gem, "~> 7.0.1"
}

gem "puma", "~> 5.0"

gem "shoryuken", "~> 6.2"
gem "aws-sdk-sqs" # shoryuken integration with AWS SDK v3+
gem "dotenv-rails" # load .env file with AWS credentials

# Need to reference all locally, otherwise it'd use the the gemspecs to try to find each gem,
# but we want to test against the local dev versions of them, not the released gems.
gem "judoscale-ruby", path: "../../judoscale-ruby"
gem "judoscale-rails", path: "../../judoscale-rails"
gem "judoscale-shoryuken", path: "../../judoscale-shoryuken"
133 changes: 133 additions & 0 deletions sample-apps/shoryuken-sample/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
PATH
remote: ../../judoscale-rails
specs:
judoscale-rails (1.6.0)
judoscale-ruby (= 1.6.0)
railties

PATH
remote: ../../judoscale-ruby
specs:
judoscale-ruby (1.6.0)

PATH
remote: ../../judoscale-shoryuken
specs:
judoscale-shoryuken (1.6.0)
judoscale-ruby (= 1.6.0)
shoryuken (>= 6.0)

GEM
remote: https://rubygems.org/
specs:
actionpack (7.0.8.1)
actionview (= 7.0.8.1)
activesupport (= 7.0.8.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.3.6)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
aws-eventstream (1.3.0)
aws-partitions (1.922.0)
aws-sdk-core (3.193.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.8)
jmespath (~> 1, >= 1.6.1)
aws-sdk-sqs (1.71.0)
aws-sdk-core (~> 3, >= 3.193.0)
aws-sigv4 (~> 1.1)
aws-sigv4 (1.8.0)
aws-eventstream (~> 1, >= 1.0.2)
builder (3.2.4)
concurrent-ruby (1.2.3)
crass (1.0.6)
dotenv (2.7.6)
dotenv-rails (2.7.6)
dotenv (= 2.7.6)
railties (>= 3.2)
erubi (1.12.0)
globalid (1.2.1)
activesupport (>= 6.1)
i18n (1.14.4)
concurrent-ruby (~> 1.0)
jmespath (1.6.2)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
method_source (1.1.0)
minitest (5.22.3)
nio4r (2.7.1)
nokogiri (1.16.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.4-x86_64-linux)
racc (~> 1.4)
puma (5.6.8)
nio4r (~> 2.0)
racc (1.7.3)
rack (2.2.9)
rack-test (2.1.0)
rack (>= 1.3)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rake (13.2.1)
shoryuken (6.2.1)
aws-sdk-core (>= 2)
concurrent-ruby
thor
thor (1.3.1)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
zeitwerk (2.6.13)

PLATFORMS
arm64-darwin-20
arm64-darwin-21
arm64-darwin-22
arm64-darwin-23
x86_64-darwin-21
x86_64-linux

DEPENDENCIES
actionpack (~> 7.0.1)
actionview (~> 7.0.1)
activejob (~> 7.0.1)
aws-sdk-sqs
dotenv-rails
judoscale-rails!
judoscale-ruby!
judoscale-shoryuken!
puma (~> 5.0)
railties (~> 7.0.1)
shoryuken (~> 6.2)

BUNDLED WITH
2.5.4
10 changes: 10 additions & 0 deletions sample-apps/shoryuken-sample/Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
proxy: npx judoscale-adapter-proxy-server

# NOTE: Enable either the `heroku_` processes or the `render_` processes based
# on which env you want to spoof locally.

heroku_rails: DYNO=web.1 bundle exec rails server
heroku_shoryuken: DYNO=worker.1 bundle exec shoryuken -R -C config/shoryuken.yml

# render_rails: RENDER_SERVICE_ID=srv-xyz RENDER_INSTANCE_ID=srv-xyz-1234 RENDER_SERVICE_TYPE=web bundle exec rails server
# render_shoryuken: RENDER_SERVICE_ID=srv-abc RENDER_INSTANCE_ID=srv-abc-1234 RENDER_SERVICE_TYPE=worker bundle exec shoryuken -R -C config/shoryuken.yml
75 changes: 75 additions & 0 deletions sample-apps/shoryuken-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Sample app for judoscale-shoryuken gem

This is a minimal Rails app to test the judoscale-shoryuken gem.

## Prerequisites

- Ruby
- Node
- [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli)
- AWS Credentials / Region

## Set up the app

Run `./bin/setup` install necessary dependencies. This will...

- Run `bundle install` to install gems

### Shoryuken / SQS setup

You also need to pass AWS credentials and an AWS region for SQS. Those can be added to a `.env` file in the repo, with the following:

```
AWS_ACCESS_KEY_ID=<key>
AWS_SECRET_ACCESS_KEY=<secret>
AWS_REGION=<region>
```

Note that AWS credentials can be setup in a few different ways. More information can be found in [Shoryuken's wiki](https://github.com/ruby-shoryuken/shoryuken/wiki/Configure-the-AWS-Client).

Shoryuken requires the SQS queues to be setup upfront. There's no need to create them via AWS console UI if you don't want to, since Shoryuken provides some helpful commands to create them, so run the following as necessary:

```bash
bundle exec dotenv shoryuken sqs create default
bundle exec dotenv shoryuken sqs create low
bundle exec dotenv shoryuken sqs create high
```

Note that we're using `dotenv` to load the `.env` file with the AWS ENV vars for Shoryuken, to be able to run these `shoryuken sqs` commands. There's a few other useful SQS commands, like `delete` and `purge`. Use `shoryuken sqs help` to learn more.

## Run the app

Run `./bin/dev` to run the app in development mode. This will...

- Use `heroku local` and a `Procfile` to start the following processes:
- A [tiny proxy server](https://github.com/judoscale/judoscale-adapter-proxy-server) that adds the `X-Request-Start` request header so we can test request queue time reporting.
- The Rails server.
- The Shoryuken server to process jobs.

## How to use this sample app

Open https://judoscale-adapter-mock.requestcatcher.com in a browser. The sample app is configured to use this endpoint as a mock for the Judoscale Adapter API. This page will monitor all API requests sent from the adapter.

Run the app. Both the Rails and Shoryuken processes will send an initial request to the API once the app boots up. These can be inspected via request catcher.

Open http://localhost:5006 to see how many jobs are waiting on each of the available queues, and to enqueue sample jobs on those queues that will be processed by the Shoryuken server slowly.

## Deploy this app to Heroku

From this directory, run the following to create a new git repo and push it to Heroku:

```sh
git init
git add .
git commit -m "prep for Heroku"
heroku create
git push heroku main
```

To install Judoscale:

```sh
# scale up a worker dyno before doing this so Judoscale picks it up
heroku ps:scale heroku_shoryuken=1
heroku addons:create judoscale:trial
```
3 changes: 3 additions & 0 deletions sample-apps/shoryuken-sample/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require_relative "config/application"

Rails.application.load_tasks
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ApplicationController < ActionController::Base
end
27 changes: 27 additions & 0 deletions sample-apps/shoryuken-sample/app/controllers/jobs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class JobsController < ApplicationController
QUEUES = %w(default low high)

def index
@available_queues = QUEUES.dup
@queues = [] # ::Shoryuken.ungrouped_queues
end

def create
job_params = params.require(:job).permit(:queue_name, :enqueue_count)

queue_name = job_params[:queue_name]
enqueue_count = job_params[:enqueue_count].to_i

if QUEUES.include?(queue_name) && enqueue_count.between?(1, 100)
1.upto(enqueue_count) {
SampleJob.set(queue: queue_name).perform_later
}

flash[:notice] = "#{enqueue_count} #{"job".pluralize(enqueue_count)} enqueued on the #{queue_name.inspect} queue."
redirect_to action: :index
else
flash[:alert] = "Please enter queue name & enqueue count."
redirect_to action: :index
end
end
end
7 changes: 7 additions & 0 deletions sample-apps/shoryuken-sample/app/jobs/application_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked

# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
end
5 changes: 5 additions & 0 deletions sample-apps/shoryuken-sample/app/jobs/sample_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class SampleJob < ApplicationJob
def perform
sleep rand(3)
end
end
42 changes: 42 additions & 0 deletions sample-apps/shoryuken-sample/app/views/jobs/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<h1>Judoscale: Shoryuken Sample</h1>

<p>
Judoscale is reporting metrics to <a href="https://judoscale-adapter-mock.requestcatcher.com" target="_blank" rel="noreferrer">https://judoscale-adapter-mock.requestcatcher.com</a>.
</p>
<p>
Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics.
</p>
<p>
Enqueue test jobs using the form below. They will be slowly processed by Shoryuken, while Judoscale collects and reports available queue metrics.
</p>

<h2>Shoryuken Queues</h2>

<% if notice %><p style="color:green"><%= notice %><% end %>
<% if alert %><p style="color:red"><%= alert %><% end %>

<% if @queues.any? %>
<ul>
<% @queues.each do |name, stats| %>
<li><%= name %>: <%= stats.map { |k, v| "#{k}: #{v}" }.join " | " %></li>
<% end %>
</ul>
<% else %>
<p>No queues found.</p>
<% end %>

<h3>Enqueue Jobs</h3>

<%= form_with scope: :job, url: jobs_path, method: :post do |f| %>
<div>
<%= f.label :queue_name %>
<%= f.select :queue_name, @available_queues, required: true %>
</div>
<div>
<%= f.label :enqueue_count %>
<%= f.number_field :enqueue_count, min: 1, max: 100, required: true %>
</div>
<div>
<%= f.button "Enqueue Jobs" %>
</div>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Judoscale: Shoryuken Sample</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
</head>

<body>
<%= yield %>
</body>
</html>
Loading

0 comments on commit 8cfe5ec

Please sign in to comment.