Skip to content
This repository has been archived by the owner on Jan 3, 2025. It is now read-only.

Commit

Permalink
Use shoryuken to allow workers to access Rails so we can trigger emai…
Browse files Browse the repository at this point in the history
…ls from the worker (#602)

* fix missing self in email API

* remove unnecessary initializers

* use shuryuken to enqueue to sqs

* correct seeds

* switch name in email API

* code changes to make shoryuken work

* add worker to wca-main network

* run rubocop

* add QUEUE_NAME to test

* stub registration email request

* fix test docker compose

* stub mailer in bulk update

* set a message_group_id

* use custom message_deduplication id and message_group_id

* run rubocop

* use set to change SQS SendMessage Parameters

* introduce variables for better readability

* change QUEUE_URL to QUEUE_NAME in infra

* add entrypoint for worker

* add missing parameters

* add shoryuken config file

* Add +x for entrypoint

* add BUILD_TAG to worker as well
  • Loading branch information
FinnIckler authored Jul 10, 2024
1 parent c0f9094 commit d66f6a3
Show file tree
Hide file tree
Showing 27 changed files with 132 additions and 212 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ jobs:
tags: ${{ steps.login-ecr.outputs.registry }}/wca-registration-worker:latest
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_TAG=${{ github.sha }}
- name: Deploy worker
run: |
aws ecs update-service --cluster wca-registration --service wca-registration-worker --force-new-deployment
2 changes: 2 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ jobs:
${{ steps.login-ecr.outputs.registry }}/wca-registration-worker:staging
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_TAG=${{ github.sha }}
- name: Deploy if triggered
if: steps.trigger-deployment.outputs.triggered == 'true'
env:
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ gem 'dynamoid', '3.8.0'
# SQS for adding data into a queue
gem 'aws-sdk-sqs'

# SQS Job Management
gem 'shoryuken'

# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
gem 'kredis'

Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ GEM
rubocop-ast (>= 1.31.1, < 2.0)
ruby-prof (1.7.0)
ruby-progressbar (1.13.0)
shoryuken (6.2.1)
aws-sdk-core (>= 2)
concurrent-ruby
thor
sqlite3 (1.7.3-aarch64-linux)
sqlite3 (1.7.3-x86_64-linux)
stringio (3.1.1)
Expand Down Expand Up @@ -381,6 +385,7 @@ DEPENDENCIES
rubocop
rubocop-rails
ruby-prof
shoryuken
sqlite3 (~> 1.4)
superconfig
tzinfo-data
Expand Down
16 changes: 5 additions & 11 deletions app/controllers/registration_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,28 @@ def count
end

def create
queue_url = ENV['QUEUE_URL'] || $sqs.get_queue_url(queue_name: 'registrations.fifo').queue_url
event_ids = params.dig('competing', 'event_ids')
comment = params.dig('competing', 'comment') || ''
guests = params['guests'] || 0
id = SecureRandom.uuid

step_data = {
created_at: Time.now.utc,
attendee_id: "#{@competition_id}-#{@user_id}",
user_id: @user_id,
competition_id: @competition_id,
lane_name: 'competing',
step: 'Event Registration',
step: 'EventRegistration',
step_details: {
registration_status: 'pending',
event_ids: event_ids,
comment: comment,
guests: guests,
},
}
message_deduplication_id = "#{step_data[:lane_name]}-#{step_data[:step]}-#{step_data[:attendee_id]}"
message_group_id = step_data[:competition_id]

$sqs.send_message({
queue_url: queue_url,
message_body: step_data.to_json,
message_group_id: id,
message_deduplication_id: id,
})
RegistrationProcessor.set(message_group_id: message_group_id, message_deduplication_id: message_deduplication_id).perform_later(step_data)

render json: { status: 'accepted', message: 'Started Registration Process' }, status: :accepted
end
Expand Down Expand Up @@ -136,8 +131,7 @@ def process_update(update_request)

# Don't send email if we only change the waiting list position
if waiting_list_position.blank?
# commented out until shuryuken PR is merged
# EmailApi.send_update_email(@competition_id, user_id, status, @current_user)
EmailApi.send_update_email(@competition_id, user_id, status, @current_user)
end

{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
# frozen_string_literal: true

require 'aws-sdk-dynamodb'
require 'dynamoid'
require 'httparty'
class RegistrationProcessor < ApplicationJob
include Shoryuken::Worker

class RegistrationProcessor
def initialize
Dynamoid.configure do |config|
config.region = EnvConfig.AWS_REGION
config.namespace = nil
if EnvConfig.CODE_ENVIRONMENT == 'development'
config.endpoint = EnvConfig.LOCALSTACK_ENDPOINT
else
config.credentials = Aws::ECSCredentials.new(retries: 3)
end
end
end
queue_as EnvConfig.QUEUE_NAME

def process_message(message)
puts "Working on Message: #{message}"
if message['step'] == 'Event Registration'
event_registration(message['competition_id'],
message['user_id'],
message['step_details']['event_ids'],
message['step_details']['comment'],
message['step_details']['guests'],
message['created_at'])
def perform(message)
Rails.logger.debug { "Working on Message: #{message}" }
if message[:step] == 'EventRegistration'
event_registration(message[:competition_id],
message[:user_id],
message[:step_details][:event_ids],
message[:step_details][:comment],
message[:step_details][:guests],
message[:created_at])
end
end

Expand Down Expand Up @@ -56,9 +44,7 @@ def event_registration(competition_id, user_id, event_ids, comment, guests, crea
else
registration.update_attributes(lanes: registration.lanes.append(competing_lane), guests: guests)
end
if EnvConfig.CODE_ENVIRONMENT == 'production'
EmailApi.send_creation_email(competition_id, user_id)
end
EmailApi.send_creation_email(competition_id, user_id)
end
# rubocop:enable Metrics/ParameterLists
end
27 changes: 0 additions & 27 deletions app/worker/env_config.rb

This file was deleted.

59 changes: 0 additions & 59 deletions app/worker/queue_poller.rb

This file was deleted.

2 changes: 2 additions & 0 deletions bin/entrypoint-worker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash -e
bundle exec shoryuken -R -C config/shoryuken.yml
2 changes: 1 addition & 1 deletion config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Application < Rails::Application
config.load_defaults 7.0

config.autoload_paths += Dir["#{config.root}/lib"]
Rails.autoloaders.main.ignore("#{config.root}/app/worker")
config.active_job.queue_adapter = :shoryuken

# Only loads a smaller set of middleware suitable for API only apps.
# Middleware like session, flash, cookies can be added back manually.
Expand Down
12 changes: 0 additions & 12 deletions config/initializers/aws.rb

This file was deleted.

25 changes: 25 additions & 0 deletions config/initializers/shoryuken.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

Shoryuken.configure_client do |config|
if Rails.env.local?
config.sqs_client = Aws::SQS::Client.new(
region: EnvConfig.AWS_REGION,
access_key_id: EnvConfig.AWS_ACCESS_KEY_ID,
secret_access_key: EnvConfig.AWS_SECRET_ACCESS_KEY,
endpoint: EnvConfig.LOCALSTACK_ENDPOINT,
verify_checksums: false,
)
end
end

Shoryuken.configure_server do |config|
if Rails.env.local?
config.sqs_client = Aws::SQS::Client.new(
region: EnvConfig.AWS_REGION,
access_key_id: EnvConfig.AWS_ACCESS_KEY_ID,
secret_access_key: EnvConfig.AWS_SECRET_ACCESS_KEY,
endpoint: EnvConfig.LOCALSTACK_ENDPOINT,
verify_checksums: false,
)
end
end
4 changes: 4 additions & 0 deletions config/shoryuken.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
queues:
- <%= ENV['QUEUE_NAME'] %>
delay: 1
concurrency: 2
29 changes: 15 additions & 14 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# Failsafe so this is never run in production (the task doesn't have permissions to create tables anyway)
unless Rails.env.production?
dynamodb = Aws::DynamoDB::Client.new(endpoint: EnvConfig.LOCALSTACK_ENDPOINT)
sqs = Aws::SQS::Client.new(endpoint: EnvConfig.LOCALSTACK_ENDPOINT)
# Create the DynamoDB Tables
table_name = EnvConfig.DYNAMO_REGISTRATIONS_TABLE
key_schema = [
Expand Down Expand Up @@ -45,23 +47,22 @@
},
]
begin
$dynamodb.create_table({
table_name: table_name,
key_schema: key_schema,
attribute_definitions: attribute_definitions,
provisioned_throughput: provisioned_throughput,
global_secondary_indexes: global_secondary_indexes,
})
dynamodb.create_table({
table_name: table_name,
key_schema: key_schema,
attribute_definitions: attribute_definitions,
provisioned_throughput: provisioned_throughput,
global_secondary_indexes: global_secondary_indexes,
})
rescue Aws::DynamoDB::Errors::ResourceInUseException
Rails.logger.debug 'Database Already exists'
end

# Create SQS Queue
queue_name = 'registrations.fifo'
$sqs.create_queue({
queue_name: queue_name,
attributes: {
FifoQueue: 'true',
},
})
sqs.create_queue({
queue_name: EnvConfig.QUEUE_NAME,
attributes: {
FifoQueue: 'true',
},
})
end
9 changes: 3 additions & 6 deletions docker-compose.backend-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ services:
PROMETHEUS_EXPORTER: "prometheus_exporter"
REDIS_URL: "redis://redis:6379"
RAILS_ENV: test
QUEUE_NAME: "registrations.fifo"
volumes:
- .:/app
- gems_volume_handler:/usr/local/bundle
Expand Down Expand Up @@ -54,21 +55,17 @@ services:
AWS_SECRET_ACCESS_KEY: "fake-access-key"
PROMETHEUS_EXPORTER: "prometheus_exporter"
DYNAMO_REGISTRATIONS_TABLE: "registrations-development"
QUEUE_NAME: "registrations.fifo"
volumes:
- .:/app
- gems_volume_worker:/usr/local/bundle
tty: true
# First, install Ruby and Node dependencies
# Start the server and bind to 0.0.0.0 (vs 127.0.0.1) so Docker's port mappings work correctly
command: >
bash -c 'bundle install &&
while ! curl http://wca_registration_handler:3000/healthcheck >/dev/null 2>&1; do
echo "Waiting for Handler to be ready" && sleep 5 ;
done && ruby -r "/app/app/worker/queue_poller.rb" -e "QueuePoller.perform"'
bash -c 'bundle install && bundle exec shoryuken -R -q registrations.fifo'
networks:
- wca-registration
healthcheck:
test: pgrep ruby || exit 1
dns:
# Set the DNS server to be the LocalStack container
- 10.0.2.20
Expand Down
Loading

0 comments on commit d66f6a3

Please sign in to comment.