(ns com.fulcrologic.datomic-cloud-backup.cloning-test
(:require
[datomic.client.api :as d]
[com.fulcrologic.datomic-cloud-backup.protocols :as dcbp]
[com.fulcrologic.datomic-cloud-backup.cloning :as cloning]
[com.fulcrologic.datomic-cloud-backup.ram-stores :refer [new-ram-store new-ram-mapper]]
[com.fulcrologic.datomic-cloud-backup.s3-backup-store :refer [new-s3-store aws-credentials?]]
[com.fulcrologic.datomic-cloud-backup.redis-id-mapper :refer [new-redis-mapper available? clear-mappings!]]
[fulcro-spec.core :refer [specification behavior component assertions =>]])
(:import (java.util UUID)))
(defonce client (d/client {:server-type :dev-local
:storage-dir :mem
:system "test"}))
(defn backup! [dbname source-connection target-store]
;; Normally, you'd not write this as a tight loop, but would instead monitor if it is returning
;; positive numbers and pause when it isn't, as an infinite loop to keep streaming.
(loop [n (cloning/backup-next-segment! dbname source-connection target-store 2)]
(when (pos? n)
(recur (cloning/backup-next-segment! dbname source-connection target-store 2)))))
(defn restore! [dbname target-conn db-store mapper]
;; Normally you'd have some hot standby continuously running this loop. The `next-start` may not yet
;; be available, so if it stays the same, delay for a bit to see if a new one arrives.
(loop [start-t 0]
(let [next-start (cloning/restore-segment! dbname target-conn db-store mapper start-t {})]
(when (< start-t next-start)
(recur next-start)))))
(comment
;; Clone a db using RAM resources. Probably runs out of memory for anything
;; but small dbs.
(let [c (d/connect client {:db-name "some-database"})
target-c (d/connect client {:db-name "restored"})
store (new-ram-store)
mapper (new-ram-mapper)]
(backup! :some-database c store)
(restore! :some-database target-c store mapper))
;; Same thing, but uses S3 resources and Redis. Should handle any db size as
;; long as Redis has space for all of the ID mappings
(let [c (d/connect client {:db-name "some-database"})
target-c (d/connect client {:db-name "restored"})
store (new-s3-store "my-s3-bucket")
mapper (new-redis-mapper {:spec {:host "localhost"}})]
(backup! :some-database c store)
(restore! :some-database target-c store mapper)))