Add build options and docker, make relay info available through env

This commit is contained in:
@s.roertgen 2024-12-12 17:36:45 +01:00
parent e5ff9265b4
commit a34d07d365
10 changed files with 158 additions and 67 deletions

1
.env Normal file
View file

@ -0,0 +1 @@
RELAY="huhuhaha"

17
Dockerfile Normal file
View file

@ -0,0 +1,17 @@
# Use a minimal OpenJDK runtime image
FROM openjdk:17-jdk-slim
# Set the working directory
WORKDIR /app
# Copy the Uberjar into the image
COPY target/app.jar .
COPY resources ./resources
# Expose the application's port
EXPOSE 8890
# Run the Uberjar
CMD ["java", "-jar", "app.jar"]

14
README.md Normal file
View file

@ -0,0 +1,14 @@
# Edufeed To AMB Transformer
Run with: `clj -M -m app.core`
Runs on port `8890`.
Sets up an endpoint `/resources` which accepts `pk` for an actory public key as a query parameter.
Results are validated against the metadata profile [Allgemeines Metadatenprofil für Bildungsressourcen](https://w3id.org/kim/amb/latest/) before being returned.
## TODO
- [ ] Add aero for configuration

39
build.clj Normal file
View file

@ -0,0 +1,39 @@
(ns build
(:require [clojure.tools.build.api :as b]))
(def lib 'app)
(def version (format "1.2.%s" (b/git-count-revs nil)))
(def class-dir "target/classes")
(def jar-file (format "target/%s-%s.jar" (name lib) version))
(def uber-file "target/app.jar")
;; delay to defer side effects (artifact downloads)
(def basis (delay (b/create-basis {:project "deps.edn"})))
(defn clean [_]
(b/delete {:path "target"}))
(defn jar [_]
(b/write-pom {:class-dir class-dir
:lib lib
:version version
:basis @basis
:src-dirs ["src"]})
(b/copy-dir {:src-dirs ["src" "resources"]
:target-dir class-dir})
(b/jar {:class-dir class-dir
:jar-file jar-file}))
(defn uber [_]
(clean nil)
(b/copy-dir {:src-dirs ["src" "resources"]
:target-dir class-dir})
(b/compile-clj {:basis @basis
:ns-compile '[app.core]
:class-dir class-dir})
(b/uber {:class-dir class-dir
:uber-file uber-file
:basis @basis
:main 'app.core}))

View file

@ -5,10 +5,14 @@
io.pedestal/pedestal.jetty {:mvn/version "0.7.1"}
org.slf4j/slf4j-simple {:mvn/version "2.0.10"}
luposlip/json-schema {:mvn/version "0.4.6"}
aero/aero {:mvn/version "1.1.6"}
net.clojars.laoc/nostr {:local/root "/home/laoc/coding/nostr-clj"}}
:aliases
{:nrepl
{:run {:main-opts ["-m" "app.core"]}
:build {:extra-deps {io.github.clojure/tools.build {:mvn/version "0.9.3"}}
:ns-default build}
:nrepl
{:extra-deps
{nrepl/nrepl {:mvn/version "1.3.0"}}
:main-opts ["-m" "nrepl.cmdline"

14
docker-compose.yml Normal file
View file

@ -0,0 +1,14 @@
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "8890:8890"
# env_file:
# - .env # Pass variables from the .env file to the container
# or via environment variables
environment:
RELAY: "ws:localhost:7778"
restart: always

1
resources/config.edn Normal file
View file

@ -0,0 +1 @@
{:web {:relay #or [#env RELAY "ws://localhost:7778"]}}

View file

@ -8,32 +8,32 @@
[json-schema.core :as json-schema]
[clojure.core.async :refer [go chan >! <!]]))
(defn validate [resources]
(let [schema (json-schema/prepare-schema
(-> "resources/schema.json"
slurp
(cheshire.core/parse-string true)))]
(try
(let [validation-results
(map (fn [resource]
(try
(when (json-schema/validate schema resource)
{:valid true :resource resource})
(catch Exception e
{:valid false :error e :resource resource})))
resources)]
(do
;; Log invalid resources
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
(println "Invalid resource:" resource "Error:" error))
;; Return only valid resources
(->> validation-results
(filter :valid)
(map :resource))))
(catch Exception e
(println "Unexpected error during validation" e)
[]))))
(def schema (json-schema/prepare-schema
(-> "resources/schema.json"
slurp
(cheshire.core/parse-string true))))
(defn validate [resources]
(try
(let [validation-results
(map (fn [resource]
(try
(when (json-schema/validate schema resource)
{:valid true :resource resource})
(catch Exception e
{:valid false :error e :resource resource})))
resources)]
(do
;; Log invalid resources
(doseq [{:keys [error resource]} (filter #(not (:valid %)) validation-results)]
#_(println "Invalid resource:" resource "Error:" error))
;; Return only valid resources
(->> validation-results
(filter :valid)
(map :resource))))
(catch Exception e
#_(println "Unexpected error during validation" e)
nil)))
(defn ok [body]
{:status 200 :body body})
@ -44,10 +44,11 @@
(go
(let [npub (get-in request [:query-params :npub])
pk (get-in request [:query-params :pk])
relay (get-in request [:relay])
filter (if pk
{:kinds [30142] :authors [pk]}
{:kinds [30142]})
resources (nostr/fetch-events "ws://localhost:7778" filter)
resources (nostr/fetch-events relay filter)
transformed (map #(edufeed/convert-30142-to-nostr-amb % true true) resources)
validate (validate transformed)
resp (if validate
@ -60,34 +61,37 @@
{:name ::resources-by-user
:enter (fn [context]
(go
(let [result (<! (get-resources (:request context)))
;; TODO check against amb schema
]
(let [result (<! (get-resources (:request context)))]
(assoc context :response (ok result)))))})
(def routes
;; Interceptor to add the WebSocket port to the request context
(defn add-relay [relay]
{:name ::add-ws-port
:enter (fn [context]
(assoc-in context [:request :relay] relay))})
(defn routes
[relay]
(route/expand-routes
#{["/resources" :get resources-by-user :route-name :resources]}))
#{["/resources" :get [(add-relay relay) resources-by-user] :route-name :resources]}))
(def service-map
{::http/routes routes
::http/type :jetty
::http/port 8890})
(defn create-service []
(http/create-server service-map))
(defn create-service [relay]
(http/create-server
(assoc service-map
::http/routes (routes relay)
::http/port 8890)))
(defn start []
(http/start (create-service)))
(comment
(http/stop (create-service)))
(defrecord WebServer []
(defrecord WebServer [relay]
component/Lifecycle
(start [this]
(println ";; Starting Web server...")
(let [server (create-service)]
(println ";; Starting Webserver")
(println ";; Using Relay: " relay)
(let [server (create-service relay)]
(assoc this :server (http/start server))))
(stop [this]
(println ";; Stopping Web server...")
@ -98,22 +102,3 @@
(defn new-web-server []
(map->WebServer {}))
;; For interactive development
(defonce server (atom nil))
(defn start-dev []
(reset! server
(http/start (http/create-server
(assoc service-map
::http/join? false)))))
(defn stop-dev []
(http/stop @server))
(defn restart []
(stop-dev)
(start-dev))
(comment
(start-dev)
(restart))

View file

@ -1,10 +1,11 @@
(ns app.core
(:require [com.stuartsierra.component :as component]
[app.system :as system]))
[app.system :as system])
(:gen-class))
(defn main []
(component/start (system/system )))
(defn -main []
(component/start (system/new-system )))
(comment
(component/stop (system/system))
(component/stop (system/new-system))
)

View file

@ -1,7 +1,22 @@
(ns app.system
(:require [com.stuartsierra.component :as component]
[aero.core :as aero]
[app.components.webserver :refer [new-web-server]]))
(defn system []
(defn new-system-map []
(component/system-map
:web (new-web-server)))
(defn configure [system]
(let [config (aero/read-config "resources/config.edn")]
(merge-with merge system config)))
(defn new-dependency-map [] {})
(defn new-system
"Create the production system"
[]
(println ";; Setting up new system")
(-> (new-system-map)
(configure)
(component/system-using (new-dependency-map))))