Skip to content

Instantly share code, notes, and snippets.

@hhutch
Created August 5, 2019 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hhutch/1cb56c3c7972ae9007500e0312c9ddd1 to your computer and use it in GitHub Desktop.
Save hhutch/1cb56c3c7972ae9007500e0312c9ddd1 to your computer and use it in GitHub Desktop.

How to make a pedestal + ss component w/ lein

this loosely follows pedestal component tutorial

http://pedestal.io/guides/pedestal-with-component

create base project

lein new pedestal-service tnbsst

add ss component to project.clj

all pedestal deps already scaffoled, using jetty for this demo

[com.stuartsierra/component "0.4.0"]

we require a Pedestal control SS component

  • implementing at the root src level

define NS with requirements

     (ns pedestal
	(:require [com.stuartsierra.component :as component]
		  [io.pedestal.http :as http]))

define a `test?` fn

It’s idiomatic in Pedestal services to include an :env key in the service map to communicate the environment of the service. This currently does not affect the behavior of the service but it’s a useful marker. Our component will leverage this idiom and will not start/stop the server if the service is configured for the test environment. The implementation is included below.

     (defn test? [service-map]
	(= :test (:env service-map)))    

define the Pedestal component record

controls start and stop lifecycle of our service

     (defrecord Pedestal [service-map service]
	component/Lifecycle
	(start [this]
	  (if service
	    this
	    (cond-> service-map
	      true http/create-server
	      (not (test? service-map)) http/start
	      true ((partial assoc this :service)))))
	(stop [this]
	  (when (and service (not (test? service-map)))
	    (http/stop service))
	  (assoc this :service nil)))

define an initilization entry point

     (defn new-pedestal []
	(map->Pedestal {}))

we need a NS for controlling our running service

useful in this case for our REPL work

  • again implement at the root level src tree

define ns and pull in required libraries

     (ns system
	(:require [com.stuartsierra.component :as component]
		  [io.pedestal.http :as http]
		  [pedestal]
		  [tnbsst.service :as service]))

create system entry-point

     (defn system [env]
	(component/system-map
	 :service-map {:env env
		       ::http/routes service/routes
		       ::http/type :jetty
		       ::http/port 8890
		       ::http/join? false}
	 :pedestal (component/using (pedestal/new-pedestal) [:service-map])))

Let’s run it in the REPL

start repl

  • cider-jack-in
  • lein repl
  • etc

load `system` NS

(require 'system)
(in-ns 'system)

create a local entry-point to work against

(def ssss (system {}))

start the service and test

(alter-var-root #'ssss component/start)

load `http://localhost:8890` … it works!

stop the service

(alter-var-root #'ssss component/stop)

you can modify the code, compile into your repl and then stop/start the service to use the newly compiled code

this could be re-written to use the -main fn in the scaffolded server NS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment