From 4307420e75fe3265f204436b11782a015ad5af41 Mon Sep 17 00:00:00 2001 From: binilsn Date: Fri, 24 Oct 2025 16:00:19 +0530 Subject: [PATCH] feat: add controller and service to add endpoints and related logs --- Gemfile | 4 +- Gemfile.lock | 12 +- app/channels/application_cable/channel.rb | 4 + app/channels/application_cable/connection.rb | 4 + app/channels/endpoint_channel.rb | 9 + app/jobs/uptime_job.rb | 10 + app/models/endpoint.rb | 28 +++ app/services/uptime_checker_service.rb | 44 +++++ app/services/uptime_rater_service.rb | 20 ++ config/cable.yml | 4 +- config/database.yml | 2 +- config/environments/development.rb | 4 + config/initializers/cors.rb | 18 +- config/puma.rb | 2 +- config/routes.rb | 8 + db/cable_schema.rb | 11 -- db/cache_schema.rb | 14 -- db/migrate/20251010060832_create_endpoints.rb | 16 ++ db/migrate/20251010063010_create_logs.rb | 12 ++ .../20251016103745_add_solid_queue.rb} | 23 ++- db/schema.rb | 186 ++++++++++++++++++ test/channels/endpoint_channel_test.rb | 8 + .../api/v1/endpoints_controller_test.rb | 7 + .../api/v1/logs_controller_test.rb | 7 + test/fixtures/endpoints.yml | 9 + test/fixtures/logs.yml | 11 ++ test/jobs/uptime_job_test.rb | 7 + test/models/endpoint_test.rb | 7 + test/models/log_test.rb | 7 + 29 files changed, 457 insertions(+), 41 deletions(-) create mode 100644 app/channels/application_cable/channel.rb create mode 100644 app/channels/application_cable/connection.rb create mode 100644 app/channels/endpoint_channel.rb create mode 100644 app/jobs/uptime_job.rb create mode 100644 app/models/endpoint.rb create mode 100644 app/services/uptime_checker_service.rb create mode 100644 app/services/uptime_rater_service.rb delete mode 100644 db/cable_schema.rb delete mode 100644 db/cache_schema.rb create mode 100644 db/migrate/20251010060832_create_endpoints.rb create mode 100644 db/migrate/20251010063010_create_logs.rb rename db/{queue_schema.rb => migrate/20251016103745_add_solid_queue.rb} (84%) create mode 100644 db/schema.rb create mode 100644 test/channels/endpoint_channel_test.rb create mode 100644 test/controllers/api/v1/endpoints_controller_test.rb create mode 100644 test/controllers/api/v1/logs_controller_test.rb create mode 100644 test/fixtures/endpoints.yml create mode 100644 test/fixtures/logs.yml create mode 100644 test/jobs/uptime_job_test.rb create mode 100644 test/models/endpoint_test.rb create mode 100644 test/models/log_test.rb diff --git a/Gemfile b/Gemfile index f043997..03475a9 100644 --- a/Gemfile +++ b/Gemfile @@ -33,7 +33,7 @@ gem "thruster", require: false # gem "image_processing", "~> 1.2" # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin Ajax possible -# gem "rack-cors" +gem "rack-cors" group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem @@ -41,7 +41,7 @@ group :development, :test do # Static analysis for security vulnerabilities [https://brakemanscanner.org/] gem "brakeman", require: false - + gem "pry", "~> 0.15.2" # Omakase Ruby styling [https://github.com/rails/rubocop-rails-omakase/] gem "rubocop-rails-omakase", require: false end diff --git a/Gemfile.lock b/Gemfile.lock index df33334..65b84c9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,9 +79,10 @@ GEM bigdecimal (3.3.1) bootsnap (1.18.6) msgpack (~> 1.2) - brakeman (7.1.1) + brakeman (7.1.2) racc builder (3.3.0) + coderay (1.1.3) concurrent-ruby (1.3.5) connection_pool (2.5.4) crass (1.0.6) @@ -138,6 +139,7 @@ GEM net-pop net-smtp marcel (1.1.0) + method_source (1.1.0) mini_mime (1.1.5) minitest (5.26.0) msgpack (1.8.0) @@ -180,6 +182,9 @@ GEM prettyprint prettyprint (0.2.0) prism (1.5.2) + pry (0.15.2) + coderay (~> 1.1) + method_source (~> 1.0) psych (5.2.6) date stringio @@ -188,6 +193,9 @@ GEM raabro (1.4.0) racc (1.8.1) rack (3.2.3) + rack-cors (3.0.0) + logger + rack (>= 3.0.14) rack-session (2.1.1) base64 (>= 0.1.0) rack (>= 3.0.0) @@ -330,7 +338,9 @@ DEPENDENCIES faraday (~> 2.14) kamal pagy (~> 9.4) + pry (~> 0.15.2) puma (>= 5.0) + rack-cors rails (~> 8.0.3) rubocop-rails-omakase solid_cable diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb new file mode 100644 index 0000000..d672697 --- /dev/null +++ b/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb new file mode 100644 index 0000000..0ff5442 --- /dev/null +++ b/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/app/channels/endpoint_channel.rb b/app/channels/endpoint_channel.rb new file mode 100644 index 0000000..7397a27 --- /dev/null +++ b/app/channels/endpoint_channel.rb @@ -0,0 +1,9 @@ +class EndpointChannel < ApplicationCable::Channel + def subscribed + stream_from "endpoint_#{params[:id]}" + end + + def unsubscribed + # Any cleanup needed when channel is unsubscribed + end +end diff --git a/app/jobs/uptime_job.rb b/app/jobs/uptime_job.rb new file mode 100644 index 0000000..7042817 --- /dev/null +++ b/app/jobs/uptime_job.rb @@ -0,0 +1,10 @@ +class UptimeJob < ApplicationJob + queue_as :default + + def perform(endpoint_id) + endpoint = Endpoint.find(endpoint_id) + return unless Endpoint::ALLOWED_TYPES.include?(endpoint.request) + + UptimeCheckerService.call(endpoint) + end +end diff --git a/app/models/endpoint.rb b/app/models/endpoint.rb new file mode 100644 index 0000000..7c6b781 --- /dev/null +++ b/app/models/endpoint.rb @@ -0,0 +1,28 @@ +class Endpoint < ApplicationRecord + ALLOWED_TYPES = %w[get post patch].freeze + + validates :name, :url, presence: true, uniqueness: true + validates :request, :duration, presence: true + + enum :duration_type, { minute: 0, hours: 1 } + has_many :logs, dependent: :destroy + + # after_create_commit :set_gid + after_create_commit :trigger_uptime_check + after_destroy_commit :discard_job + + def discard_job + return if job_id.blank? + + job = SolidQueue::Job.scheduled.find_by(active_job_id: job_id) + job.discard if job.present? + end + + def set_gid + update(gid: to_gid_param) + end + + def trigger_uptime_check + UptimeJob.perform_now(self.id) + end +end diff --git a/app/services/uptime_checker_service.rb b/app/services/uptime_checker_service.rb new file mode 100644 index 0000000..e2b36e4 --- /dev/null +++ b/app/services/uptime_checker_service.rb @@ -0,0 +1,44 @@ +class UptimeCheckerService + attr_accessor :endpoint, :type, :url, :logs, :status, :response_code + + def initialize(endpoint) + @endpoint = endpoint + @url = endpoint.url + @type = endpoint.request + @logs = endpoint.logs + @status = "" + @log = @endpoint.logs.build + @response_code = 404 + end + + def self.call(endpoint) + new(endpoint).check + end + + def check + return unless Endpoint::ALLOWED_TYPES.include?(type) + begin + latency = Benchmark.realtime do + response = Faraday.public_send(type, url) + @response_code = response.status + end + latency =(latency * 1000).round(2) + rescue => e + @response_code = 404 + Rails.logger.error("Error checking #{url}: #{e.message}") + end + + @log.assign_attributes(response_code: @response_code, latency:) + endpoint.transaction do + if @log.save && UptimeRaterService.call(endpoint) && endpoint.touch(:last_updated) + Rails.logger.error("OK!") + else + Rails.logger.error("Error") + end + delay = endpoint.minute? ? endpoint.duration.minutes : endpoint.duration.hours + job = UptimeJob.set(wait: delay).perform_later(endpoint.id) + endpoint.update(job_id: job.job_id) + ActionCable.server.broadcast("endpoint_#{endpoint.id}", endpoint.as_json) + end + end +end diff --git a/app/services/uptime_rater_service.rb b/app/services/uptime_rater_service.rb new file mode 100644 index 0000000..e44b044 --- /dev/null +++ b/app/services/uptime_rater_service.rb @@ -0,0 +1,20 @@ + +class UptimeRaterService + attr_accessor :endpoint, :logs + + def initialize(endpoint) + @endpoint = endpoint + @logs = @endpoint.logs + end + + def self.call(endpoint) + new(endpoint).rate + end + + def rate + total_requests = logs.size + success_requests = logs.where(response_code: 200).size + uptime = (success_requests/total_requests.to_f) * 100 + endpoint.update(uptime:) + end +end diff --git a/config/cable.yml b/config/cable.yml index b9adc5a..b2b9685 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -3,7 +3,9 @@ # not a terminal started via bin/rails console! Add "console" to any action or any ERB template view # to make the web console appear. development: - adapter: async + adapter: solid_cable + polling_interval: 0.1.seconds + message_retention: 1.day test: adapter: test diff --git a/config/database.yml b/config/database.yml index 2640cb5..eb8179b 100644 --- a/config/database.yml +++ b/config/database.yml @@ -12,7 +12,7 @@ default: &default development: <<: *default database: storage/development.sqlite3 - + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. diff --git a/config/environments/development.rb b/config/environments/development.rb index e7722fc..0f41d77 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -53,6 +53,10 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true + # Use Solid Queue in Development. + config.active_job.queue_adapter = :solid_queue + + config.solid_queue.logger = ActiveSupport::Logger.new(STDOUT) # Raises error for missing translations. # config.i18n.raise_on_missing_translations = true diff --git a/config/initializers/cors.rb b/config/initializers/cors.rb index 0c5dd99..835d425 100644 --- a/config/initializers/cors.rb +++ b/config/initializers/cors.rb @@ -5,12 +5,12 @@ # Read more: https://github.com/cyu/rack-cors -# Rails.application.config.middleware.insert_before 0, Rack::Cors do -# allow do -# origins "example.com" -# -# resource "*", -# headers: :any, -# methods: [:get, :post, :put, :patch, :delete, :options, :head] -# end -# end +Rails.application.config.middleware.insert_before 0, Rack::Cors do + allow do + origins "*" + + resource "*", + headers: :any, + methods: [ :get, :post, :put, :patch, :delete, :options, :head ] + end +end diff --git a/config/puma.rb b/config/puma.rb index a248513..4d3ec97 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -34,7 +34,7 @@ plugin :tmp_restart # Run the Solid Queue supervisor inside of Puma for single-server deployments -plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] +plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] || Rails.env.development? # Specify the PID file. Defaults to tmp/pids/server.pid in development. # In other environments, only set the PID file if requested. diff --git a/config/routes.rb b/config/routes.rb index a125ef0..e473bdc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,12 @@ Rails.application.routes.draw do + mount ActionCable.server => "/api/v1/cable" + namespace :api do + namespace :v1 do + resources :endpoints do + resources :logs + end + end + end # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500. diff --git a/db/cable_schema.rb b/db/cable_schema.rb deleted file mode 100644 index 2366660..0000000 --- a/db/cable_schema.rb +++ /dev/null @@ -1,11 +0,0 @@ -ActiveRecord::Schema[7.1].define(version: 1) do - create_table "solid_cable_messages", force: :cascade do |t| - t.binary "channel", limit: 1024, null: false - t.binary "payload", limit: 536870912, null: false - t.datetime "created_at", null: false - t.integer "channel_hash", limit: 8, null: false - t.index ["channel"], name: "index_solid_cable_messages_on_channel" - t.index ["channel_hash"], name: "index_solid_cable_messages_on_channel_hash" - t.index ["created_at"], name: "index_solid_cable_messages_on_created_at" - end -end diff --git a/db/cache_schema.rb b/db/cache_schema.rb deleted file mode 100644 index 6005a29..0000000 --- a/db/cache_schema.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -ActiveRecord::Schema[7.2].define(version: 1) do - create_table "solid_cache_entries", force: :cascade do |t| - t.binary "key", limit: 1024, null: false - t.binary "value", limit: 536870912, null: false - t.datetime "created_at", null: false - t.integer "key_hash", limit: 8, null: false - t.integer "byte_size", limit: 4, null: false - t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size" - t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size" - t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true - end -end diff --git a/db/migrate/20251010060832_create_endpoints.rb b/db/migrate/20251010060832_create_endpoints.rb new file mode 100644 index 0000000..82dd157 --- /dev/null +++ b/db/migrate/20251010060832_create_endpoints.rb @@ -0,0 +1,16 @@ +class CreateEndpoints < ActiveRecord::Migration[8.0] + def change + create_table :endpoints do |t| + t.string :url, null: false, index: true + t.string :request, null: false + t.string :name, null: false + t.integer :duration, null: false, default: 0 + t.integer :duration_type, null: false, default: 0 + t.decimal :uptime, precision: 5, scale: 2 + t.string :job_id + t.datetime :last_updated + + t.timestamps + end + end +end diff --git a/db/migrate/20251010063010_create_logs.rb b/db/migrate/20251010063010_create_logs.rb new file mode 100644 index 0000000..41daf76 --- /dev/null +++ b/db/migrate/20251010063010_create_logs.rb @@ -0,0 +1,12 @@ +class CreateLogs < ActiveRecord::Migration[8.0] + def change + create_table :logs do |t| + t.belongs_to :endpoint + t.integer :response_code + t.string :status + t.integer :latency, default: 0 + + t.timestamps + end + end +end diff --git a/db/queue_schema.rb b/db/migrate/20251016103745_add_solid_queue.rb similarity index 84% rename from db/queue_schema.rb rename to db/migrate/20251016103745_add_solid_queue.rb index 85194b6..006a943 100644 --- a/db/queue_schema.rb +++ b/db/migrate/20251016103745_add_solid_queue.rb @@ -1,4 +1,14 @@ -ActiveRecord::Schema[7.1].define(version: 1) do +class AddSolidQueue < ActiveRecord::Migration[8.0] + def change + create_table "solid_cable_messages", force: :cascade do |t| + t.binary "channel", limit: 1024, null: false + t.binary "payload", limit: 536870912, null: false + t.datetime "created_at", null: false + t.integer "channel_hash", limit: 8, null: false + t.index [ "channel" ], name: "index_solid_cable_messages_on_channel" + t.index [ "channel_hash" ], name: "index_solid_cable_messages_on_channel_hash" + t.index [ "created_at" ], name: "index_solid_cable_messages_on_created_at" + end create_table "solid_queue_blocked_executions", force: :cascade do |t| t.bigint "job_id", null: false t.string "queue_name", null: false @@ -120,10 +130,21 @@ t.index [ "key" ], name: "index_solid_queue_semaphores_on_key", unique: true end + create_table "solid_cache_entries", force: :cascade do |t| + t.binary "key", limit: 1024, null: false + t.binary "value", limit: 536870912, null: false + t.datetime "created_at", null: false + t.integer "key_hash", limit: 8, null: false + t.integer "byte_size", limit: 4, null: false + t.index [ "byte_size" ], name: "index_solid_cache_entries_on_byte_size" + t.index [ "key_hash", "byte_size" ], name: "index_solid_cache_entries_on_key_hash_and_byte_size" + t.index [ "key_hash" ], name: "index_solid_cache_entries_on_key_hash", unique: true + end add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + end end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000..9664774 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,186 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[8.0].define(version: 2025_10_16_103745) do + create_table "endpoints", force: :cascade do |t| + t.string "url", null: false + t.string "request", null: false + t.string "name", null: false + t.integer "duration", default: 0, null: false + t.integer "duration_type", default: 0, null: false + t.decimal "uptime", precision: 5, scale: 2 + t.string "job_id" + t.datetime "last_updated" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["url"], name: "index_endpoints_on_url" + end + + create_table "logs", force: :cascade do |t| + t.integer "endpoint_id" + t.integer "response_code" + t.string "status" + t.integer "latency", default: 0 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["endpoint_id"], name: "index_logs_on_endpoint_id" + end + + create_table "solid_cable_messages", force: :cascade do |t| + t.binary "channel", limit: 1024, null: false + t.binary "payload", limit: 536870912, null: false + t.datetime "created_at", null: false + t.integer "channel_hash", limit: 8, null: false + t.index ["channel"], name: "index_solid_cable_messages_on_channel" + t.index ["channel_hash"], name: "index_solid_cable_messages_on_channel_hash" + t.index ["created_at"], name: "index_solid_cable_messages_on_created_at" + end + + create_table "solid_cache_entries", force: :cascade do |t| + t.binary "key", limit: 1024, null: false + t.binary "value", limit: 536870912, null: false + t.datetime "created_at", null: false + t.integer "key_hash", limit: 8, null: false + t.integer "byte_size", limit: 4, null: false + t.index ["byte_size"], name: "index_solid_cache_entries_on_byte_size" + t.index ["key_hash", "byte_size"], name: "index_solid_cache_entries_on_key_hash_and_byte_size" + t.index ["key_hash"], name: "index_solid_cache_entries_on_key_hash", unique: true + end + + create_table "solid_queue_blocked_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.string "concurrency_key", null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.index ["concurrency_key", "priority", "job_id"], name: "index_solid_queue_blocked_executions_for_release" + t.index ["expires_at", "concurrency_key"], name: "index_solid_queue_blocked_executions_for_maintenance" + t.index ["job_id"], name: "index_solid_queue_blocked_executions_on_job_id", unique: true + end + + create_table "solid_queue_claimed_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.bigint "process_id" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_claimed_executions_on_job_id", unique: true + t.index ["process_id", "job_id"], name: "index_solid_queue_claimed_executions_on_process_id_and_job_id" + end + + create_table "solid_queue_failed_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.text "error" + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_failed_executions_on_job_id", unique: true + end + + create_table "solid_queue_jobs", force: :cascade do |t| + t.string "queue_name", null: false + t.string "class_name", null: false + t.text "arguments" + t.integer "priority", default: 0, null: false + t.string "active_job_id" + t.datetime "scheduled_at" + t.datetime "finished_at" + t.string "concurrency_key" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["active_job_id"], name: "index_solid_queue_jobs_on_active_job_id" + t.index ["class_name"], name: "index_solid_queue_jobs_on_class_name" + t.index ["finished_at"], name: "index_solid_queue_jobs_on_finished_at" + t.index ["queue_name", "finished_at"], name: "index_solid_queue_jobs_for_filtering" + t.index ["scheduled_at", "finished_at"], name: "index_solid_queue_jobs_for_alerting" + end + + create_table "solid_queue_pauses", force: :cascade do |t| + t.string "queue_name", null: false + t.datetime "created_at", null: false + t.index ["queue_name"], name: "index_solid_queue_pauses_on_queue_name", unique: true + end + + create_table "solid_queue_processes", force: :cascade do |t| + t.string "kind", null: false + t.datetime "last_heartbeat_at", null: false + t.bigint "supervisor_id" + t.integer "pid", null: false + t.string "hostname" + t.text "metadata" + t.datetime "created_at", null: false + t.string "name", null: false + t.index ["last_heartbeat_at"], name: "index_solid_queue_processes_on_last_heartbeat_at" + t.index ["name", "supervisor_id"], name: "index_solid_queue_processes_on_name_and_supervisor_id", unique: true + t.index ["supervisor_id"], name: "index_solid_queue_processes_on_supervisor_id" + end + + create_table "solid_queue_ready_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_ready_executions_on_job_id", unique: true + t.index ["priority", "job_id"], name: "index_solid_queue_poll_all" + t.index ["queue_name", "priority", "job_id"], name: "index_solid_queue_poll_by_queue" + end + + create_table "solid_queue_recurring_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.string "task_key", null: false + t.datetime "run_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_recurring_executions_on_job_id", unique: true + t.index ["task_key", "run_at"], name: "index_solid_queue_recurring_executions_on_task_key_and_run_at", unique: true + end + + create_table "solid_queue_recurring_tasks", force: :cascade do |t| + t.string "key", null: false + t.string "schedule", null: false + t.string "command", limit: 2048 + t.string "class_name" + t.text "arguments" + t.string "queue_name" + t.integer "priority", default: 0 + t.boolean "static", default: true, null: false + t.text "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["key"], name: "index_solid_queue_recurring_tasks_on_key", unique: true + t.index ["static"], name: "index_solid_queue_recurring_tasks_on_static" + end + + create_table "solid_queue_scheduled_executions", force: :cascade do |t| + t.bigint "job_id", null: false + t.string "queue_name", null: false + t.integer "priority", default: 0, null: false + t.datetime "scheduled_at", null: false + t.datetime "created_at", null: false + t.index ["job_id"], name: "index_solid_queue_scheduled_executions_on_job_id", unique: true + t.index ["scheduled_at", "priority", "job_id"], name: "index_solid_queue_dispatch_all" + end + + create_table "solid_queue_semaphores", force: :cascade do |t| + t.string "key", null: false + t.integer "value", default: 1, null: false + t.datetime "expires_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["expires_at"], name: "index_solid_queue_semaphores_on_expires_at" + t.index ["key", "value"], name: "index_solid_queue_semaphores_on_key_and_value" + t.index ["key"], name: "index_solid_queue_semaphores_on_key", unique: true + end + + add_foreign_key "solid_queue_blocked_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_claimed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_failed_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_ready_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_recurring_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade + add_foreign_key "solid_queue_scheduled_executions", "solid_queue_jobs", column: "job_id", on_delete: :cascade +end diff --git a/test/channels/endpoint_channel_test.rb b/test/channels/endpoint_channel_test.rb new file mode 100644 index 0000000..4d81eb6 --- /dev/null +++ b/test/channels/endpoint_channel_test.rb @@ -0,0 +1,8 @@ +require "test_helper" + +class EndpointChannelTest < ActionCable::Channel::TestCase + # test "subscribes" do + # subscribe + # assert subscription.confirmed? + # end +end diff --git a/test/controllers/api/v1/endpoints_controller_test.rb b/test/controllers/api/v1/endpoints_controller_test.rb new file mode 100644 index 0000000..a1a4fcf --- /dev/null +++ b/test/controllers/api/v1/endpoints_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class Api::V1::EndpointsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/api/v1/logs_controller_test.rb b/test/controllers/api/v1/logs_controller_test.rb new file mode 100644 index 0000000..7f7f4cc --- /dev/null +++ b/test/controllers/api/v1/logs_controller_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class Api::V1::LogsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/fixtures/endpoints.yml b/test/fixtures/endpoints.yml new file mode 100644 index 0000000..8be84a5 --- /dev/null +++ b/test/fixtures/endpoints.yml @@ -0,0 +1,9 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + url: MyString + request: 1 + +two: + url: MyString + request: 1 diff --git a/test/fixtures/logs.yml b/test/fixtures/logs.yml new file mode 100644 index 0000000..d7a3329 --- /dev/null +++ b/test/fixtures/logs.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/jobs/uptime_job_test.rb b/test/jobs/uptime_job_test.rb new file mode 100644 index 0000000..47867c8 --- /dev/null +++ b/test/jobs/uptime_job_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UptimeJobTest < ActiveJob::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/endpoint_test.rb b/test/models/endpoint_test.rb new file mode 100644 index 0000000..a7cf383 --- /dev/null +++ b/test/models/endpoint_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class EndpointTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/log_test.rb b/test/models/log_test.rb new file mode 100644 index 0000000..7c8f6f5 --- /dev/null +++ b/test/models/log_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class LogTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end