Compare commits

1 Commits

Author SHA1 Message Date
Charles N Wyble
ed34a28c89 WIP: uncommitted changes before archiving
💘 Generated with Crush

Assisted-by: GLM-4.7 via Crush <crush@charm.land>
2026-01-13 20:14:07 -05:00
5 changed files with 70 additions and 45 deletions

View File

@@ -6,9 +6,13 @@ WORKDIR /home/opam/website_monitor
RUN sudo apt-get update && sudo apt-get install -y \ RUN sudo apt-get update && sudo apt-get install -y \
pkg-config \ pkg-config \
libssl-dev \ libssl-dev \
libgmp-dev \
libev-dev \
libpq-dev \
ca-certificates \ ca-certificates \
m4 \ m4 \
postgresql-client \ postgresql-client \
wget \
&& sudo rm -rf /var/lib/apt/lists/* && sudo rm -rf /var/lib/apt/lists/*
# Copy project files # Copy project files
@@ -38,6 +42,7 @@ RUN apt-get update && apt-get install -y \
libssl3 \ libssl3 \
ca-certificates \ ca-certificates \
tzdata \ tzdata \
wget \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Copy binaries from build stage # Copy binaries from build stage

View File

@@ -4,7 +4,14 @@ open Dream
open Lwt.Infix open Lwt.Infix
let () = let () =
let env = Dream.run ~interface:"0.0.0.0" ~port:8080 @@ fun _ -> (* Create database pool *)
ignore (Database.create_pool ());
(* Initialize database schema *)
Lwt.catch
(fun () -> Database.init_schema ())
(fun _exn -> Lwt.return_unit) (* Continue even if init fails *)
(* CORS middleware *) (* CORS middleware *)
let cors = let cors =
Dream.middleware Dream.middleware
@@ -64,7 +71,7 @@ let () =
Dream.get "/stats/summary" Website_monitor_api.get_stats_summary; Dream.get "/stats/summary" Website_monitor_api.get_stats_summary;
]); ]);
(* Admin dashboard routes - server-side rendered with server-reason-react *) (* Admin dashboard routes *)
Dream.get "/" Website_monitor_ui.serve_dashboard; Dream.get "/" Website_monitor_ui.serve_dashboard;
Dream.get "/dashboard" Website_monitor_ui.serve_dashboard; Dream.get "/dashboard" Website_monitor_ui.serve_dashboard;
Dream.get "/dashboard/websites" Website_monitor_ui.serve_websites_page; Dream.get "/dashboard/websites" Website_monitor_ui.serve_websites_page;
@@ -76,16 +83,12 @@ let () =
] ]
in in
(* Apply middlewares and router *)
Dream.logger ~level:`Debug
@@ cors
@@ logger
@@ router
in
(* Start monitoring scheduler *) (* Start monitoring scheduler *)
Website_monitor_scheduler.start (); Website_monitor_scheduler.start ();
(* Run the server *) (* Run the server *)
env Dream.run ~interface:"0.0.0.0" ~port:8080
@@ Dream.logger ~level:`Debug
@@ cors
@@ logger
@@ router

View File

@@ -20,5 +20,13 @@
(ocaml-protoc-plugin (>= 8.0)) (ocaml-protoc-plugin (>= 8.0))
(cohttp-lwt-unix (>= 5.0)) (cohttp-lwt-unix (>= 5.0))
(ocaml-ssl (>= 0.7)) (ocaml-ssl (>= 0.7))
calendar) ptime
ptime-lwt
fmt
logs
logs-fmt
angstrom
base64
ipaddr
cmdliner)
(license MIT)) (license MIT))

View File

@@ -4,14 +4,22 @@ open Lwt.Infix
open Caqti_type open Caqti_type
(* Database connection pool *) (* Database connection pool *)
let pool = ref None
let pool_size = 5 let pool_size = 5
(* Database URL from environment *) (* Get database URL from environment *)
let db_url = let db_url () =
try Sys.getenv "DATABASE_URL" try Sys.getenv "DATABASE_URL"
with Not_found -> with Not_found ->
"postgresql://monitor_user:changeme@localhost:5432/website_monitor" "postgresql://monitor_user:changeme@localhost:5432/website_monitor"
(* Create database pool *)
let create_pool () =
let driver = Caqti_lwt.connect (Caqti_driver_postgres.connect ()) in
let uri = Caqti_uri.of_string_exn (db_url ()) in
let p = Caqti_pool.create ~max_size:pool_size driver uri in
pool := Some p
(* Website model *) (* Website model *)
module Website = struct module Website = struct
type t = { type t = {
@@ -49,6 +57,22 @@ module Website = struct
created_at; updated_at; last_checked; last_status } created_at; updated_at; last_checked; last_status }
end end
(* Get database connection pool *)
let get_pool () =
match !pool with
| Some p -> p
| None -> failwith "Database pool not initialized"
(* Set database pool (called by Dream middleware) *)
let set_pool p =
pool := Some p
(* Initialize database pool *)
let initialize_pool () =
()
(* Note: When using Dream.sql_pool, the pool is passed via Dream.sql *)
(* Alert model *) (* Alert model *)
module Alert = struct module Alert = struct
type t = { type t = {
@@ -101,12 +125,6 @@ module CheckHistory = struct
{ id; website_id; status_code; response_time; error_message; checked_at } { id; website_id; status_code; response_time; error_message; checked_at }
end end
(* Database connection pool *)
let pool =
let driver = Caqti_block.connect (Caqti_driver_postgres.connect ()) in
let uri = Caqti_uri.of_string_exn db_url in
Caqti_pool.create ~max_size:pool_size driver uri
(* Initialize database schema *) (* Initialize database schema *)
let init_schema () = let init_schema () =
let queries = let queries =
@@ -114,7 +132,8 @@ let init_schema () =
Alerts.create_table; Alerts.create_table;
CheckHistories.create_table |] CheckHistories.create_table |]
in in
Lwt_list.iter_s (fun q -> Caqti_request.exec pool q ()) queries let p = get_pool () in
Lwt_list.iter_s (fun q -> Caqti_request.exec p q ()) queries
>>= fun () -> >>= fun () ->
Logs.app (fun m -> m "Database schema initialized"); Logs.app (fun m -> m "Database schema initialized");
Lwt.return_unit Lwt.return_unit

View File

@@ -9,24 +9,18 @@ bug-reports: "https://github.com/username/website_monitor/issues"
depends: [ depends: [
"ocaml" {>= "5.0"} "ocaml" {>= "5.0"}
"dune" {>= "3.11"} "dune" {>= "3.11"}
"dream" {>= "1.0.0"} "dream"
"reason" {>= "3.8"}
"server-reason-react" {>= "5.0"}
"caqti" {>= "2.1"} "caqti" {>= "2.1"}
"caqti-dream" {>= "2.1"} "caqti-lwt"
"lwt" {>= "5.6"} "lwt" {>= "5.6"}
"lwt_ppx" "lwt_ppx"
"yojson" {>= "2.1"} "yojson" {>= "2.1"}
"ocaml-protoc-plugin" {>= "8.0"}
"cohttp-lwt-unix" {>= "5.0"} "cohttp-lwt-unix" {>= "5.0"}
"ocaml-ssl" {>= "0.7"}
"calendar" {>= "2.4"}
"cmdliner" "cmdliner"
"ipaddr" "ipaddr"
"ptime" "ptime"
"fmt" "fmt"
"logs" {>= "0.7"} "logs" {>= "0.7"}
"logs-fmt"
"angstrom" "angstrom"
"base64" "base64"
] ]
@@ -35,7 +29,3 @@ build: [
["dune" "build" "-p" name "-j" jobs] ["dune" "build" "-p" name "-j" jobs]
] ]
dev-repo: "git+https://github.com/username/website_monitor.git" dev-repo: "git+https://github.com/username/website_monitor.git"
url {
src: "https://github.com/username/website_monitor/archive/refs/tags/v1.0.0.tar.gz"
checksum: "md5=dummy-checksum"
}