class SyncContactJob < ApplicationJob
queue_as :external
BACKOFF = ->(executions) do
(2**executions) + rand(0.0..1.0) # exponential + jitter, in seconds
end
class CreateOutboxEvents < ActiveRecord::Migration[7.1]
def change
create_table :outbox_events do |t|
t.string :event_type, null: false
t.string :aggregate_type, null: false
t.string :aggregate_id, null: false
class ProcessPaymentWorker
include Sidekiq::Worker
sidekiq_options queue: :critical, retry: 10
sidekiq_retry_in do |count, exception|
class LastSeenTracker
THROTTLE = 5.minutes
PENDING_KEY = "pending:last_seen".freeze
class << self
def touch(user_id, at: Time.current)
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import EmailOutbox
import queue
import time
from dataclasses import dataclass, field, replace
from typing import Any, Dict, Tuple
CREATE TYPE outbox_status AS ENUM ('pending', 'retry', 'processing', 'done', 'dead');
CREATE TABLE outbox_events (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
dedupe_key TEXT NOT NULL,
topic TEXT NOT NULL,
class ImportRun < ApplicationRecord
enum status: { pending: 0, running: 1, completed: 2, failed: 3 }
def percent
return 0 if total.to_i.zero?
[(processed.to_f / total * 100).round, 100].min
namespace :cleanup do
desc "Enqueue a job to purge expired sessions"
task expired_sessions: :environment do
job = ExpiredSessionCleanupJob.perform_later
Rails.logger.info("[cleanup:expired_sessions] enqueued job #{job.job_id}")
end
require "securerandom"
class RedisMutex
class LockError < StandardError; end
UNLOCK_SCRIPT = <<~LUA.freeze
<?php
namespace App\Http\Controllers\Auth;
use App\Events\UserRegistered;
use App\Http\Controllers\Controller;
<?php
namespace App\Jobs;
use App\Models\Invoice;
use App\Services\StripeGateway;