💎 🔗 Advanced Webhooks with TuskLang Ruby

Ruby Documentation

🔗 Advanced Webhooks with TuskLang Ruby

"We don't bow to any king" - Ruby Edition

Transform your Ruby applications with TuskLang's advanced webhook system. From real-time notifications to complex event-driven architectures, TuskLang webhooks provide the power and flexibility you need to build responsive, scalable applications.

🚀 Quick Start

Basic Webhook Setup

require 'tusklang'
require 'tusklang/webhooks'

Initialize webhook system

webhook_system = TuskLang::Webhooks::System.new

Register a simple webhook

webhook_system.register('user.created') do |payload| puts "New user created: #{payload['user']['email']}" # Send welcome email, create profile, etc. end

Trigger the webhook

webhook_system.trigger('user.created', { user: { id: 123, email: 'alice@example.com', name: 'Alice' }, timestamp: Time.now.iso8601 })

TuskLang Configuration

config/webhooks.tsk

[webhooks] enabled: true timeout: "30s" retry_attempts: 3 retry_delay: "5s"

[webhooks.endpoints] user_created: "https://api.example.com/webhooks/user-created" order_placed: "https://api.example.com/webhooks/order-placed" payment_processed: "https://api.example.com/webhooks/payment-processed"

[webhooks.security] signature_header: "X-Webhook-Signature" signature_algorithm: "sha256" secret_key: @env("WEBHOOK_SECRET", "default-secret")

[webhooks.rate_limiting] requests_per_minute: 100 burst_limit: 20

🎯 Core Features

1. Event-Driven Architecture

require 'tusklang/webhooks'

class WebhookManager include TuskLang::Webhooks::EventEmitter def initialize @config = TuskLang.parse_file('config/webhooks.tsk') setup_webhooks end private def setup_webhooks # User events on('user.created') do |payload| send_welcome_email(payload['user']) create_user_profile(payload['user']) notify_admin(payload['user']) end on('user.updated') do |payload| update_search_index(payload['user']) invalidate_cache(payload['user']['id']) end on('user.deleted') do |payload| archive_user_data(payload['user']) remove_from_search_index(payload['user']['id']) end # Order events on('order.placed') do |payload| process_payment(payload['order']) update_inventory(payload['order']) send_order_confirmation(payload['order']) end on('order.shipped') do |payload| send_tracking_email(payload['order']) update_order_status(payload['order']['id']) end # Payment events on('payment.processed') do |payload| update_order_status(payload['payment']['order_id']) send_receipt(payload['payment']) end on('payment.failed') do |payload| notify_user_of_failure(payload['payment']) retry_payment(payload['payment']) end end def send_welcome_email(user) # Implementation end def create_user_profile(user) # Implementation end def notify_admin(user) # Implementation end end

2. Advanced Webhook Handlers

require 'tusklang/webhooks'
require 'json'

class AdvancedWebhookHandler include TuskLang::Webhooks::Handler def initialize @config = TuskLang.parse_file('config/webhooks.tsk') @rate_limiter = TuskLang::RateLimiter.new( requests_per_minute: @config['webhooks']['rate_limiting']['requests_per_minute'], burst_limit: @config['webhooks']['rate_limiting']['burst_limit'] ) end # Handle incoming webhooks def handle_webhook(request) # Verify signature return unauthorized unless verify_signature(request) # Rate limiting return rate_limited unless @rate_limiter.allow?(request.ip) # Parse payload payload = JSON.parse(request.body.read) event_type = request.headers['X-Event-Type'] # Process based on event type case event_type when 'user.created' handle_user_created(payload) when 'order.placed' handle_order_placed(payload) when 'payment.processed' handle_payment_processed(payload) else handle_unknown_event(event_type, payload) end { status: 'success', message: 'Webhook processed' } rescue => e log_error(e) { status: 'error', message: e.message } end private def verify_signature(request) signature = request.headers[@config['webhooks']['security']['signature_header']] expected_signature = generate_signature(request.body.read) signature == expected_signature end def generate_signature(payload) secret = @config['webhooks']['security']['secret_key'] algorithm = @config['webhooks']['security']['signature_algorithm'] case algorithm when 'sha256' OpenSSL::HMAC.hexdigest('SHA256', secret, payload) when 'sha1' OpenSSL::HMAC.hexdigest('SHA1', secret, payload) else raise "Unsupported signature algorithm: #{algorithm}" end end def handle_user_created(payload) user = payload['user'] # Create user profile profile = UserProfile.create!( user_id: user['id'], email: user['email'], name: user['name'], created_at: Time.parse(user['created_at']) ) # Send welcome email UserMailer.welcome_email(user['email']).deliver_later # Update analytics Analytics.track('user.created', { user_id: user['id'], source: payload['source'], timestamp: Time.now }) end def handle_order_placed(payload) order = payload['order'] # Process payment payment_result = PaymentProcessor.process(order['payment']) if payment_result.success? # Update order status order_record = Order.find(order['id']) order_record.update!(status: 'paid', payment_id: payment_result.payment_id) # Update inventory InventoryManager.update_stock(order['items']) # Send confirmation OrderMailer.confirmation_email(order['customer_email'], order).deliver_later else # Handle payment failure handle_payment_failure(order, payment_result.error) end end def handle_payment_processed(payload) payment = payload['payment'] # Update order status order = Order.find(payment['order_id']) order.update!(status: 'paid', payment_processed_at: Time.now) # Send receipt PaymentMailer.receipt_email(payment['customer_email'], payment).deliver_later # Update analytics Analytics.track('payment.processed', { order_id: payment['order_id'], amount: payment['amount'], currency: payment['currency'] }) end def handle_unknown_event(event_type, payload) Rails.logger.warn "Unknown webhook event: #{event_type}" Rails.logger.debug "Payload: #{payload.inspect}" end def log_error(error) Rails.logger.error "Webhook processing error: #{error.message}" Rails.logger.error error.backtrace.join("\n") end end

3. Webhook Middleware

require 'tusklang/webhooks'

class WebhookMiddleware def initialize(app) @app = app @config = TuskLang.parse_file('config/webhooks.tsk') end def call(env) request = Rack::Request.new(env) # Check if this is a webhook request if webhook_request?(request) handle_webhook_request(request) else @app.call(env) end end private def webhook_request?(request) request.path.start_with?('/webhooks/') && request.post? end def handle_webhook_request(request) handler = AdvancedWebhookHandler.new result = handler.handle_webhook(request) [ result[:status] == 'success' ? 200 : 400, { 'Content-Type' => 'application/json' }, [result.to_json] ] end end

In config/application.rb

module MyApp class Application < Rails::Application # Add webhook middleware config.middleware.use WebhookMiddleware end end

4. Webhook Testing Framework

require 'tusklang/webhooks'
require 'rspec'

RSpec.describe 'Webhook System' do let(:webhook_system) { TuskLang::Webhooks::System.new } let(:config) { TuskLang.parse_file('spec/fixtures/webhooks.tsk') } before do webhook_system.configure(config) end describe 'user.created webhook' do it 'sends welcome email' do expect(UserMailer).to receive(:welcome_email).with('alice@example.com') webhook_system.trigger('user.created', { user: { email: 'alice@example.com', name: 'Alice' } }) end it 'creates user profile' do expect { webhook_system.trigger('user.created', { user: { id: 123, email: 'alice@example.com', name: 'Alice' } }) }.to change(UserProfile, :count).by(1) end it 'tracks analytics event' do expect(Analytics).to receive(:track).with('user.created', hash_including( user_id: 123 )) webhook_system.trigger('user.created', { user: { id: 123, email: 'alice@example.com', name: 'Alice' } }) end end describe 'order.placed webhook' do let(:order_payload) do { order: { id: 456, customer_email: 'bob@example.com', items: [{ product_id: 1, quantity: 2 }], payment: { method: 'credit_card', amount: 99.99 } } } end it 'processes payment' do expect(PaymentProcessor).to receive(:process).with( hash_including(method: 'credit_card', amount: 99.99) ).and_return(double(success?: true, payment_id: 'pay_123')) webhook_system.trigger('order.placed', order_payload) end it 'updates inventory' do expect(InventoryManager).to receive(:update_stock).with( [{ product_id: 1, quantity: 2 }] ) webhook_system.trigger('order.placed', order_payload) end it 'sends confirmation email' do expect(OrderMailer).to receive(:confirmation_email).with( 'bob@example.com', hash_including(id: 456) ) webhook_system.trigger('order.placed', order_payload) end end describe 'webhook security' do it 'verifies signature' do request = double( headers: { 'X-Webhook-Signature' => 'invalid_signature' }, body: double(read: '{"test": "data"}'), ip: '127.0.0.1' ) handler = AdvancedWebhookHandler.new result = handler.handle_webhook(request) expect(result[:status]).to eq('error') end it 'enforces rate limiting' do request = double( headers: { 'X-Webhook-Signature' => 'valid_signature' }, body: double(read: '{"test": "data"}'), ip: '127.0.0.1' ) # Make too many requests 101.times do handler = AdvancedWebhookHandler.new handler.handle_webhook(request) end # Last request should be rate limited handler = AdvancedWebhookHandler.new result = handler.handle_webhook(request) expect(result[:status]).to eq('rate_limited') end end end

🔧 Advanced Configuration

Webhook Retry Logic

require 'tusklang/webhooks'

class RetryableWebhook include TuskLang::Webhooks::Retryable def initialize @config = TuskLang.parse_file('config/webhooks.tsk') @retry_attempts = @config['webhooks']['retry_attempts'] @retry_delay = parse_duration(@config['webhooks']['retry_delay']) end def send_webhook(endpoint, payload) with_retry(attempts: @retry_attempts, delay: @retry_delay) do response = HTTP.timeout(@config['webhooks']['timeout']) .post(endpoint, json: payload) unless response.status.success? raise "Webhook failed with status #{response.status}" end response end end private def parse_duration(duration_string) case duration_string when /(\d+)s/ $1.to_i when /(\d+)m/ $1.to_i * 60 when /(\d+)h/ $1.to_i * 3600 else 5 # Default 5 seconds end end end

Webhook Queue System

require 'tusklang/webhooks'
require 'sidekiq'

class WebhookWorker include Sidekiq::Worker def perform(event_type, payload, endpoint = nil) webhook_system = TuskLang::Webhooks::System.new config = TuskLang.parse_file('config/webhooks.tsk') # Use endpoint from payload or config target_endpoint = endpoint || config['webhooks']['endpoints'][event_type] if target_endpoint # Send to external endpoint send_external_webhook(target_endpoint, event_type, payload) else # Process internally webhook_system.trigger(event_type, payload) end end private def send_external_webhook(endpoint, event_type, payload) config = TuskLang.parse_file('config/webhooks.tsk') headers = { 'Content-Type' => 'application/json', 'X-Event-Type' => event_type, 'X-Webhook-Signature' => generate_signature(payload.to_json) } response = HTTP.timeout(config['webhooks']['timeout']) .headers(headers) .post(endpoint, json: payload) unless response.status.success? raise "External webhook failed: #{response.status} - #{response.body}" end Rails.logger.info "External webhook sent successfully to #{endpoint}" end def generate_signature(payload) secret = TuskLang.parse_file('config/webhooks.tsk')['webhooks']['security']['secret_key'] OpenSSL::HMAC.hexdigest('SHA256', secret, payload) end end

Usage

WebhookWorker.perform_async('user.created', { user: { id: 123, email: 'alice@example.com' } })

🚀 Performance Optimization

Webhook Batching

require 'tusklang/webhooks'

class BatchedWebhookProcessor def initialize @batch_size = 100 @batch_timeout = 30 # seconds @batches = {} @mutex = Mutex.new end def add_to_batch(event_type, payload) @mutex.synchronize do @batches[event_type] ||= [] @batches[event_type] << payload if @batches[event_type].size >= @batch_size process_batch(event_type) end end end def process_batch(event_type) batch = @batches[event_type] @batches[event_type] = [] # Process batch in background Thread.new do begin batch.each do |payload| WebhookWorker.perform_async(event_type, payload) end rescue => e Rails.logger.error "Batch processing error: #{e.message}" end end end def start_batch_timer Thread.new do loop do sleep @batch_timeout @mutex.synchronize do @batches.each do |event_type, batch| process_batch(event_type) unless batch.empty? end end end end end end

Webhook Monitoring

require 'tusklang/webhooks'

class WebhookMonitor include TuskLang::Webhooks::Monitorable def initialize @metrics = TuskLang::Metrics::Collector.new @config = TuskLang.parse_file('config/webhooks.tsk') end def track_webhook_event(event_type, payload, response_time) @metrics.increment("webhook.events.#{event_type}") @metrics.histogram("webhook.response_time", response_time) if response_time > @config['webhooks']['timeout'] @metrics.increment("webhook.timeouts.#{event_type}") end end def track_webhook_error(event_type, error) @metrics.increment("webhook.errors.#{event_type}") @metrics.increment("webhook.errors.#{error.class.name}") end def get_webhook_stats { total_events: @metrics.get("webhook.events.total"), average_response_time: @metrics.get_average("webhook.response_time"), error_rate: @metrics.get_error_rate("webhook.errors"), top_events: @metrics.get_top("webhook.events", 10) } end end

🔒 Security Best Practices

Webhook Authentication

require 'tusklang/webhooks'

class SecureWebhookHandler def initialize @config = TuskLang.parse_file('config/webhooks.tsk') end def authenticate_webhook(request) # Verify signature return false unless verify_signature(request) # Check IP whitelist return false unless ip_whitelisted?(request.ip) # Verify timestamp (prevent replay attacks) return false unless verify_timestamp(request) true end private def verify_signature(request) signature = request.headers['X-Webhook-Signature'] payload = request.body.read expected_signature = generate_signature(payload) # Use constant-time comparison to prevent timing attacks Rack::Utils.secure_compare(signature, expected_signature) end def ip_whitelisted?(ip) whitelist = @config['webhooks']['security']['ip_whitelist'] || [] whitelist.include?(ip) end def verify_timestamp(request) timestamp = request.headers['X-Webhook-Timestamp'] return false unless timestamp webhook_time = Time.at(timestamp.to_i) current_time = Time.now # Allow 5-minute window for clock skew (current_time - webhook_time).abs <= 300 end end

📊 Monitoring and Debugging

Webhook Dashboard

require 'tusklang/webhooks'

class WebhookDashboardController < ApplicationController def index @stats = webhook_monitor.get_webhook_stats @recent_events = webhook_monitor.get_recent_events(limit: 50) @error_logs = webhook_monitor.get_error_logs(limit: 20) end def event_details @event = webhook_monitor.get_event_details(params[:id]) @payload = JSON.pretty_generate(@event.payload) @response = @event.response end def retry_failed event_id = params[:id] webhook_monitor.retry_failed_event(event_id) redirect_to webhook_dashboard_path, notice: 'Webhook retry initiated' end private def webhook_monitor @webhook_monitor ||= WebhookMonitor.new end end

🎯 Real-World Examples

E-commerce Webhook System

config/ecommerce-webhooks.tsk

[ecommerce_webhooks] enabled: true timeout: "60s" retry_attempts: 5

[ecommerce_webhooks.events] order_created: "https://api.shopify.com/webhooks/orders/create" order_updated: "https://api.shopify.com/webhooks/orders/updated" order_cancelled: "https://api.shopify.com/webhooks/orders/cancelled" payment_processed: "https://api.stripe.com/webhooks/payment_intent.succeeded" inventory_updated: "https://api.shopify.com/webhooks/inventory_levels/update"

[ecommerce_webhooks.handlers] order_created: "OrderCreatedHandler" order_updated: "OrderUpdatedHandler" payment_processed: "PaymentProcessedHandler"

class EcommerceWebhookSystem
  def initialize
    @config = TuskLang.parse_file('config/ecommerce-webhooks.tsk')
    @handlers = load_handlers
  end
  
  def process_webhook(event_type, payload)
    handler_class = @handlers[event_type]
    return unless handler_class
    
    handler = handler_class.constantize.new
    handler.process(payload)
  end
  
  private
  
  def load_handlers
    @config['ecommerce_webhooks']['handlers']
  end
end

class OrderCreatedHandler def process(payload) order = payload['order'] # Create order in local system local_order = Order.create!( external_id: order['id'], customer_email: order['email'], total: order['total_price'], currency: order['currency'], status: 'pending' ) # Process line items order['line_items'].each do |item| OrderItem.create!( order: local_order, product_id: item['product_id'], quantity: item['quantity'], price: item['price'] ) end # Send confirmation email OrderMailer.confirmation_email(local_order).deliver_later # Update inventory InventoryManager.reserve_items(local_order) end end

This comprehensive webhook system provides the foundation for building robust, scalable event-driven applications with TuskLang and Ruby. The combination of TuskLang's configuration flexibility and Ruby's expressive syntax creates a powerful platform for handling complex webhook scenarios.