SlideShare a Scribd company logo
1 of 36
Download to read offline
Reloadable ClojureApp
Stuart Sierra's Component Framework
» Signifier
» 93-00
» 01-16 ・通信系スタートアップで開
発
» 16 7 Signifier Clojure
» Clojure
Clojure
» REPL
»
» ->Prismatic Schema
REPL
» pallet/alembic ... (load-project)
» user=> (use 'my-ns.a-namespace :reload)
» :reload
»
» defmulti/defprotocol/macro
» Closure
clojure/tools.namespace
user=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
user=> (refresh)
:reloading (com.example.util com.example.app com.example.app-test)
:ok
clojure/tools.namespace
» ring.middleware.reload
(ns myapp
(:require
[compojure.core :refer [GET defroutes]]
[ring.middleware.reload :refer [wrap-reload]]))
(defroutes app
(GET "/" [] "hello world"))
(def reloadable-app
(wrap-reload app))
» reload >> weavejester/ns-tracker >> clojure/tools.namespace
c.t.namespace
»
» def ・シングルトン
(def state-of-world (ref {}))
(def object-handle (atom nil))
c.t.namespace
»
(defn create-application []
{:state-of-world (ref {})
:object-handle (atom nil)})
def DB connection,
config, etc...
...
» Stuart Sierra's Component
» Record/Map
・終了処理を管理する
» API
»
» Map (System)
»
» danielsz/system
»
» Jetty, HTTP kit, Carmine, ElasticSearch, etc...
» (e.g. Jetty)
» API
project.clj
(defproject a-project-ec "0.1.0-SNAPSHOT"
(...snip...)
:dependencies
[[funcool/clojure.jdbc "0.9.0"]
[hikari-cp "1.7.4"]
[honeysql "0.8.0"]
[http-kit "2.1.18"]
[metosin/compojure-api "1.1.7" :exclusions [org.clojure/tools.reader]]
[migratus "0.8.31"]
[org.clojure/clojure "1.8.0"]
[org.danielsz/system "0.3.1"]
[org.postgresql/postgresql "9.4.1211"]
[ring "1.5.0" :exclusions [commons-codec
org.clojure/tools.reader]]]
(...snip...)
user.clj
(ns user
(:require
[system.repl :as repl :refer [system set-init! start stop reset]]
[clojure.tools.namespace.repl :refer [refresh]]
[a-project-ec.systems :refer [dev-system]]))
(set-init! #'dev-system)
(defn reload []
(stop)
(refresh :after 'system.repl/reset))
systems.clj
(ns a-project-ec.systems
(:require [com.stuartsierra.component :as component]
[a-project-ec.components.customer-master :refer [new-customer-master]]
[a-project-ec.components.jetty :refer [new-web-server]]
[a-project-ec.components.migratus :refer [new-migratus]]
[a-project-ec.components.orders :refer [new-orders]]
[a-project-ec.components.product-master :refer [new-product-master]]
[a-project-ec.components.ring-handler :refer [new-ring-handler]]
[system.components.hikari :refer [new-hikari-cp]]
[system.components.repl-server :refer [new-repl-server]]
[system.core :refer [defsystem]]))
systems.clj
(defn dev-system []
(component/system-map
:customer-master (new-customer-master)
:hikari-cp (component/using
(new-hikari-cp {:adapter "postgresql"
:username "a-project"
:password "password"
:database-name "a-project"
:server-name "localhost"
:port-number 5432})
[:migratus])
:migratus (new-migratus {:store :database
:migration-dir "migrations"
:db {:classname "org.postgresql.ds.PGSimpleDataSource"
:subprotocol "postgresql"
:subname "//localhost:5432/a-project"
:user "a-project"
:password "a-project123"}})
:orders (component/using
(new-orders)
[:hikari-cp :product-master :customer-master])
:product-master (new-product-master)
:ring-handler (component/using
(new-ring-handler) [:customer-master
:orders
:product-master])
:web (component/using
(new-web-server (Integer. (or (env :http-port) "3000")))
{:handler :ring-handler})))
(defn prod-system []
(dev-system))
systems.clj
» component/system-map Component SystemMap
» component/using Map/Record Vector
Inject
(component/system-map
:customer-master (new-customer-master)
:hikari-cp (component/using
(new-hikari-cp {:adapter "postgresql"
:username "a-project"
:password "password"
:database-name "a-project"
:server-name "localhost"
:port-number 5432})
[:migratus])
:migratus (new-migratus {:store :database
:migration-dir "migrations"
...
System
» System
user=>(start)
»
user=>(stop)
»
user=>(reload)
product-master.clj
(ns a-project-ec.components.product-master
(:require [again.core :as again]
[cheshire.core :as json]
[com.stuartsierra.component :as component]
[a-project-ec.retry :as retry]
[org.httpkit.client :as http]
[schema.core :as s]
[slingshot.slingshot :refer [throw+]]
[taoensso.timbre :as log]))
product-master.clj
(def sheetsu-api-url "https://sheetsu.com/apis/v1.0/123456abcde")
(def sheetsu-basic-auth-user "a-user")
(def sheetsu-basic-auth-pass "a-password")
(defn load-product-master
[product-master]
(again/with-retries
retry/http-call-intervals
(let [options {:basic-auth [sheetsu-basic-auth-user
sheetsu-basic-auth-pass]}
{:keys [status
headers
body
error] :as resp} @(http/get sheetsu-api-url options)]
(if (or (nil? status) (>= status 300))
(do (log/warn "load-product-master: failed to call sheetsu api." error)
(throw+ {:type :rest-api-failure :message error :status status}))
(reset! product-master (json/parse-string body true)))))
product-master)
product-master.clj
(defrecord ProductMaster [product-master]
component/Lifecycle
(start [component]
(log/info "Starting ProductMaster...")
(assoc component :product-master (load-product-master product-master)))
(stop [component]
(log/info "Stopping ProductMaster...")
(dissoc component :product-master)))
(defn new-product-master
[]
(map->ProductMaster {:product-master (atom nil)}))
def ...
(defn load-product-master
[product-master sheetsu-api-url
sheetsu-basic-auth-user sheetwsu-basic-auth-pass]
(again/with-retries
retry/http-call-intervals
(let [options {:basic-auth [sheetsu-basic-auth-user
sheetsu-basic-auth-pass]}
{:keys [status
headers
body
error] :as resp} @(http/get sheetsu-api-url options)]
(if (or (nil? status) (>= status 300))
(do (log/warn "load-product-master: failed to call sheetsu api." error)
(throw+ {:type :rest-api-failure :message error :status status}))
(reset! product-master (json/parse-string body true)))))
product-master)
(defrecord ProductMaster [product-master]
component/Lifecycle
(start [component]
(log/info "Starting ProductMaster...")
(assoc component :product-master (load-product-master product-master)))
(stop [component]
(log/info "Stopping ProductMaster...")
(dissoc component :product-master)))
(defn new-product-master
[url user pass]
(map->ProductMaster {:sheetsu-api-url url
:sheetsu-basic-auth-user user
:sheetsu-basic-auth-pass pass
:product-master (atom nil)}))
systems.clj config
:product-master (new-product-master "https://sheetsu.com/apis/v1.0/123456abcde"
"a-user" "a-pass")
Injection hikari-cp-> orders
(ns a-project-ec.systems
(:require ...
[system.components.hikari :refer [new-hikari-cp]]))
:hikari-cp (component/using
(new-hikari-cp {:adapter "postgresql"
:username "a-project"
:password "password"
:database-name "a-project"
:server-name "localhost"
:port-number 5432})
[:migratus])
:orders (component/using
(new-orders)
[:hikari-cp :product-master :customer-master])
Injection orders.clj
(ns a-project-ec.components.orders
(:require [clj-uuid :as uuid]
[com.stuartsierra.component :as component]
[a-project-ec.crud :as crud]
[a-project-ec.schema.a-project :refer :all]
[jdbc.core :as jdbc]
[schema.core :as s]
[taoensso.timbre :as log]))
Injection orders.clj
(def salt "12345668-abcd-1111-2222-1a2b3c4d5e6f")
(defrecord Orders [hikari-cp product-master customer-master])
(defn new-orders []
(map->Orders {}))
Injection orders.clj
(s/defn order-item-id :- s/Uuid
[order-id :- s/Uuid
product-code :- ProductCode]
(uuid/v5 order-id product-code))
(s/defn create :- s/Uuid
[this :- Orders
order :- OrderRequest]
(log/info "order-req:" order)
(let [{:keys [hikari-cp product-master customer-master]} this
order-id (-> (uuid/v1)
(uuid/v5 salt)
(uuid/v5 (:retailer-id order)))
order (-> order
(assoc :id order-id)
(assoc :order-items (map #(assoc %
:id (order-item-id order-id (:product-code %))
:order-id order-id)
(:order-items order))))]
(jdbc/atomic hikari-cp
(let [id (crud/create hikari-cp :orders (dissoc order :order-items))]
(for [order-item (:order-items order)]
(crud/create hikari-cp :order-items order-item))
id))))
Injection crud.clj
(s/defn create :- s/Str
[conn
table :- s/Keyword
kv :- {s/Keyword s/Any}]
(let [kv (assoc kv
:created-at :%now
:updated-at :%now)
sql (-> (h/insert-into table)
(h/values [kv])
(ph/returning :id)
sql/format)]
(log/debug "create:" sql)
(:id (first (jdbc/fetch conn sql)))))
Close over
» systems.clj
:ring-handler (component/using
(new-ring-handler) [:customer-master
:orders
:product-master])
» ring-handler.clj
(ns a-project-ec.components.ring-handler
(:require [com.stuartsierra.component :as component]
[compojure.api.sweet :refer :all]
[a-project-ec.routes.customer-master :refer [customer-master-routes]]
[a-project-ec.routes.order :refer [order-routes]]
[a-project-ec.routes.product-master :refer [product-master-routes]]
[ring.util.http-response :refer :all]
[schema.core :as s]
[taoensso.timbre :as log]))
Close over
(defmethod compojure.api.meta/restructure-param :components
[_ components acc]
(update-in acc [:letks] into
[components `(::components ~'+compojure-api-request+)]))
(defn wrap-components [handler components]
(fn [req]
(handler (assoc req ::components components))))
(s/defn make-handler
[this handler-fn]
(wrap-components handler-fn this))
Close over
(def app
(api
{:swagger
{:ui "/a-project-ec/api-docs"
:spec "/a-project-ec/swagger.json"
:data {:basePath "/"
:info {:title "a-project E-commerce API"
:description "API for Cigar Retailers"}}}}
customer-master-routes
order-routes
product-master-routes))
(s/defrecord RingHandler [product-master]
component/Lifecycle
(start [component]
(log/info "Starting RingHandler...")
(assoc component
:handler-fn (make-handler component #'app)))
(stop [component]
(log/info "Shutting down RingHandler...")
(dissoc component :deps :handler-fn)))
(s/defn new-ring-handler
[] (map->RingHandler {}))
Ring-handler Jetty Inject
(ns a-project-ec.components.jetty
(:require [a-project-ec.components.ring-handler :as h]
[taoensso.timbre :as log]
[com.stuartsierra.component :as component]
[ring.adapter.jetty :refer [run-jetty]]
[schema.core :as s])
(:import (org.eclipse.jetty.server Server)))
Ring-handler Jetty Inject
(s/defrecord WebServer
[port :- s/Int
server :- Server
handler :- h/->RingHandler]
component/Lifecycle
(start [component]
(log/info "Starting Jetty...")
(if (nil? (:server component))
(try
(let [handler (:handler-fn handler)
server (run-jetty handler {:port port :join? false})]
(assoc component :server server))
(catch java.net.BindException e
(log/warn e "Jetty has already started.")
component))
component))
(stop [component]
(log/info "Shutting down Jetty...")
(when server
(try (.stop server)
(catch Throwable t
(log/warn t "Failed to stp Jetty.")))
(dissoc component :server))))
Ring-handler Jetty Inject
(defn new-web-server
([port]
(map->WebServer {:port port}))
([port handler]
(map->WebServer {:port port :handler handler})))
compojure-api Component
(defroutes order-routes
(context "/a-project-ec/api/orders" []
:tags ["Orders"]
(POST "/" []
:components [orders]
:return OrderId
:summary " "
:body [order-request OrderRequest]
(ok (orders/create orders order-request)))))
FAQ
»
» System
»
» System Inject
»
» system.repl/system (:orders
system.repl/system) Component
Component
» (reload) REPL
» REPL
»
» DB ring middleware
REPL
»
» @k2nakamura
» http://signifier.jp

More Related Content

What's hot

React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7Dongho Cho
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術名辰 洪
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionIan Barber
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersIan Barber
 
Angular 1 + es6
Angular 1 + es6Angular 1 + es6
Angular 1 + es6장현 한
 
Drush. Secrets come out.
Drush. Secrets come out.Drush. Secrets come out.
Drush. Secrets come out.Alex S
 
JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]Stephen Chin
 
"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita GalkinFwdays
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsTimur Shemsedinov
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189Mahmoud Samir Fayed
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Nko workshop - node js crud & deploy
Nko workshop - node js crud & deployNko workshop - node js crud & deploy
Nko workshop - node js crud & deploySimon Su
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeMongoDB
 
How to stand on the shoulders of giants
How to stand on the shoulders of giantsHow to stand on the shoulders of giants
How to stand on the shoulders of giantsIan Barber
 

What's hot (20)

React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術RxJS - 封裝程式的藝術
RxJS - 封裝程式的藝術
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
 
Angular 1 + es6
Angular 1 + es6Angular 1 + es6
Angular 1 + es6
 
Drush. Secrets come out.
Drush. Secrets come out.Drush. Secrets come out.
Drush. Secrets come out.
 
JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]JavaFX 2.0 With Alternative Languages [Portuguese]
JavaFX 2.0 With Alternative Languages [Portuguese]
 
"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin"Auth for React.js APP", Nikita Galkin
"Auth for React.js APP", Nikita Galkin
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
FwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.jsFwDays 2021: Metarhia Technology Stack for Node.js
FwDays 2021: Metarhia Technology Stack for Node.js
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Nko workshop - node js crud & deploy
Nko workshop - node js crud & deployNko workshop - node js crud & deploy
Nko workshop - node js crud & deploy
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
Building Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at StripeBuilding Real Time Systems on MongoDB Using the Oplog at Stripe
Building Real Time Systems on MongoDB Using the Oplog at Stripe
 
How to stand on the shoulders of giants
How to stand on the shoulders of giantsHow to stand on the shoulders of giants
How to stand on the shoulders of giants
 

Viewers also liked

Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアルkwatch
 
今すぐ使えるクラウドとPostgreSQL
今すぐ使えるクラウドとPostgreSQL今すぐ使えるクラウドとPostgreSQL
今すぐ使えるクラウドとPostgreSQLSoudai Sone
 
HAWQをCDHで動かしてみた
HAWQをCDHで動かしてみたHAWQをCDHで動かしてみた
HAWQをCDHで動かしてみたadachij2002
 
Osc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatypeOsc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatypeToshi Harada
 
Ivsctonightandday2016winter moringsession awsreinvent2016recap
Ivsctonightandday2016winter moringsession awsreinvent2016recapIvsctonightandday2016winter moringsession awsreinvent2016recap
Ivsctonightandday2016winter moringsession awsreinvent2016recapTadashi Okazaki
 
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜Takeshi Wakamatsu
 
レシピブログのサービス設計と今後の展望
レシピブログのサービス設計と今後の展望レシピブログのサービス設計と今後の展望
レシピブログのサービス設計と今後の展望Masaki Nakagawa
 
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループAPCommunications-recruit
 
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo NagataInsight Technology, Inc.
 
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介IBM Analytics Japan
 
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database AnalyticsPL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database AnalyticsKohei KaiGai
 
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016Takayuki Shimizukawa
 
サーバーワークス re:invent_2016~新サービス・アップデート紹介~
サーバーワークス re:invent_2016~新サービス・アップデート紹介~サーバーワークス re:invent_2016~新サービス・アップデート紹介~
サーバーワークス re:invent_2016~新サービス・アップデート紹介~Serverworks Co.,Ltd.
 
35歳でDBAになった私がデータベースを壊して学んだこと
35歳でDBAになった私がデータベースを壊して学んだこと35歳でDBAになった私がデータベースを壊して学んだこと
35歳でDBAになった私がデータベースを壊して学んだことShinnosuke Akita
 
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...Insight Technology, Inc.
 
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫Insight Technology, Inc.
 
地方エンジニアがPostgreSQLを通じて成長した話
地方エンジニアがPostgreSQLを通じて成長した話地方エンジニアがPostgreSQLを通じて成長した話
地方エンジニアがPostgreSQLを通じて成長した話Soudai Sone
 
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...Insight Technology, Inc.
 
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac DawsonCODE BLUE
 

Viewers also liked (20)

Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
 
今すぐ使えるクラウドとPostgreSQL
今すぐ使えるクラウドとPostgreSQL今すぐ使えるクラウドとPostgreSQL
今すぐ使えるクラウドとPostgreSQL
 
HAWQをCDHで動かしてみた
HAWQをCDHで動かしてみたHAWQをCDHで動かしてみた
HAWQをCDHで動かしてみた
 
PostgreSQLアーキテクチャ入門
PostgreSQLアーキテクチャ入門PostgreSQLアーキテクチャ入門
PostgreSQLアーキテクチャ入門
 
Osc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatypeOsc2015 hokkaido postgresql-semi-stuructured-datatype
Osc2015 hokkaido postgresql-semi-stuructured-datatype
 
Ivsctonightandday2016winter moringsession awsreinvent2016recap
Ivsctonightandday2016winter moringsession awsreinvent2016recapIvsctonightandday2016winter moringsession awsreinvent2016recap
Ivsctonightandday2016winter moringsession awsreinvent2016recap
 
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜
初心者がAWSでWebサービスを始めるまで 〜たった3ステップでWebページは公開できる〜
 
レシピブログのサービス設計と今後の展望
レシピブログのサービス設計と今後の展望レシピブログのサービス設計と今後の展望
レシピブログのサービス設計と今後の展望
 
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ
【自社プロダクト開発エンジニア募集中】エーピーコミュニケーションズ 先進開発グループ
 
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata
[D31] PostgreSQLでスケールアウト構成を構築しよう by Yugo Nagata
 
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介
最上級の簡易性を備えたオープンソースDBクラウド基盤 Composeのご紹介
 
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database AnalyticsPL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
PL/CUDA - Fusion of HPC Grade Power with In-Database Analytics
 
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016仕事で使うちょっとしたコードをOSSとして開発メンテしていく- Django Redshift Backend の開発 - PyCon JP 2016
仕事で使うちょっとしたコードをOSSとして開発メンテしていく - Django Redshift Backend の開発 - PyCon JP 2016
 
サーバーワークス re:invent_2016~新サービス・アップデート紹介~
サーバーワークス re:invent_2016~新サービス・アップデート紹介~サーバーワークス re:invent_2016~新サービス・アップデート紹介~
サーバーワークス re:invent_2016~新サービス・アップデート紹介~
 
35歳でDBAになった私がデータベースを壊して学んだこと
35歳でDBAになった私がデータベースを壊して学んだこと35歳でDBAになった私がデータベースを壊して学んだこと
35歳でDBAになった私がデータベースを壊して学んだこと
 
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...
20160927_守るべきは、大量の情報資産を管理するデータベース! ~ユーザ事例から見るデータベースのセキュリティ対策~ by 株式会社インサイトテクノ...
 
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
20160929_InnoDBの全文検索を使ってみた by 株式会社インサイトテクノロジー 中村範夫
 
地方エンジニアがPostgreSQLを通じて成長した話
地方エンジニアがPostgreSQLを通じて成長した話地方エンジニアがPostgreSQLを通じて成長した話
地方エンジニアがPostgreSQLを通じて成長した話
 
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...
[data analytics showcase] B16: Live Demo! データ分析基盤を支えるデータレプリケーション技術とデータワークロード分...
 
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
 

Similar to リローダブルClojureアプリケーション

CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak PROIDEA
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesLindsay Holmwood
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar SimovićJS Belgrade
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJSSandi Barr
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Eyal Vardi
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to CeleryIdan Gazit
 
ClojureScript: The Good Parts
ClojureScript: The Good PartsClojureScript: The Good Parts
ClojureScript: The Good PartsKent Ohashi
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksMongoDB
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsFrancois Zaninotto
 
Airflow presentation
Airflow presentationAirflow presentation
Airflow presentationIlias Okacha
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020Matt Raible
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentialsPramod Kadam
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-senseBen Lin
 
Infrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsInfrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsMykyta Protsenko
 
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Tenchi Security
 
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Alexandre Sieira
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomyDongmin Yu
 

Similar to リローダブルClojureアプリケーション (20)

CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović"Angular.js Concepts in Depth" by Aleksandar Simović
"Angular.js Concepts in Depth" by Aleksandar Simović
 
Angular and The Case for RxJS
Angular and The Case for RxJSAngular and The Case for RxJS
Angular and The Case for RxJS
 
Finding Clojure
Finding ClojureFinding Clojure
Finding Clojure
 
Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)Angular 2 Architecture (Bucharest 26/10/2016)
Angular 2 Architecture (Bucharest 26/10/2016)
 
An Introduction to Celery
An Introduction to CeleryAn Introduction to Celery
An Introduction to Celery
 
ClojureScript: The Good Parts
ClojureScript: The Good PartsClojureScript: The Good Parts
ClojureScript: The Good Parts
 
Fun Teaching MongoDB New Tricks
Fun Teaching MongoDB New TricksFun Teaching MongoDB New Tricks
Fun Teaching MongoDB New Tricks
 
Bonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node jsBonnes pratiques de développement avec Node js
Bonnes pratiques de développement avec Node js
 
Airflow presentation
Airflow presentationAirflow presentation
Airflow presentation
 
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 202010 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
10 Excellent Ways to Secure Spring Boot Applications - Okta Webinar 2020
 
Laravel5 Introduction and essentials
Laravel5 Introduction and essentialsLaravel5 Introduction and essentials
Laravel5 Introduction and essentials
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-sense
 
Infrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and OpsInfrastructure-as-code: bridging the gap between Devs and Ops
Infrastructure-as-code: bridging the gap between Devs and Ops
 
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
 
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
Shopping for Vulnerabilities - How Cloud Service Provider Marketplaces can He...
 
Introduction to angular js
Introduction to angular jsIntroduction to angular js
Introduction to angular js
 
Play vs Rails
Play vs RailsPlay vs Rails
Play vs Rails
 
Presto anatomy
Presto anatomyPresto anatomy
Presto anatomy
 

Recently uploaded

WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...Jittipong Loespradit
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 

Recently uploaded (20)

WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 

リローダブルClojureアプリケーション

  • 2. » Signifier » 93-00 » 01-16 ・通信系スタートアップで開 発 » 16 7 Signifier Clojure » Clojure
  • 4. REPL » pallet/alembic ... (load-project) » user=> (use 'my-ns.a-namespace :reload) » :reload » » defmulti/defprotocol/macro » Closure
  • 5. clojure/tools.namespace user=> (require '[clojure.tools.namespace.repl :refer [refresh]]) nil user=> (refresh) :reloading (com.example.util com.example.app com.example.app-test) :ok
  • 6. clojure/tools.namespace » ring.middleware.reload (ns myapp (:require [compojure.core :refer [GET defroutes]] [ring.middleware.reload :refer [wrap-reload]])) (defroutes app (GET "/" [] "hello world")) (def reloadable-app (wrap-reload app)) » reload >> weavejester/ns-tracker >> clojure/tools.namespace
  • 7. c.t.namespace » » def ・シングルトン (def state-of-world (ref {})) (def object-handle (atom nil))
  • 8. c.t.namespace » (defn create-application [] {:state-of-world (ref {}) :object-handle (atom nil)}) def DB connection, config, etc...
  • 9. ... » Stuart Sierra's Component » Record/Map ・終了処理を管理する » API » » Map (System) »
  • 10. » danielsz/system » » Jetty, HTTP kit, Carmine, ElasticSearch, etc... » (e.g. Jetty) » API
  • 11. project.clj (defproject a-project-ec "0.1.0-SNAPSHOT" (...snip...) :dependencies [[funcool/clojure.jdbc "0.9.0"] [hikari-cp "1.7.4"] [honeysql "0.8.0"] [http-kit "2.1.18"] [metosin/compojure-api "1.1.7" :exclusions [org.clojure/tools.reader]] [migratus "0.8.31"] [org.clojure/clojure "1.8.0"] [org.danielsz/system "0.3.1"] [org.postgresql/postgresql "9.4.1211"] [ring "1.5.0" :exclusions [commons-codec org.clojure/tools.reader]]] (...snip...)
  • 12. user.clj (ns user (:require [system.repl :as repl :refer [system set-init! start stop reset]] [clojure.tools.namespace.repl :refer [refresh]] [a-project-ec.systems :refer [dev-system]])) (set-init! #'dev-system) (defn reload [] (stop) (refresh :after 'system.repl/reset))
  • 13. systems.clj (ns a-project-ec.systems (:require [com.stuartsierra.component :as component] [a-project-ec.components.customer-master :refer [new-customer-master]] [a-project-ec.components.jetty :refer [new-web-server]] [a-project-ec.components.migratus :refer [new-migratus]] [a-project-ec.components.orders :refer [new-orders]] [a-project-ec.components.product-master :refer [new-product-master]] [a-project-ec.components.ring-handler :refer [new-ring-handler]] [system.components.hikari :refer [new-hikari-cp]] [system.components.repl-server :refer [new-repl-server]] [system.core :refer [defsystem]]))
  • 14. systems.clj (defn dev-system [] (component/system-map :customer-master (new-customer-master) :hikari-cp (component/using (new-hikari-cp {:adapter "postgresql" :username "a-project" :password "password" :database-name "a-project" :server-name "localhost" :port-number 5432}) [:migratus]) :migratus (new-migratus {:store :database :migration-dir "migrations" :db {:classname "org.postgresql.ds.PGSimpleDataSource" :subprotocol "postgresql" :subname "//localhost:5432/a-project" :user "a-project" :password "a-project123"}}) :orders (component/using (new-orders) [:hikari-cp :product-master :customer-master]) :product-master (new-product-master) :ring-handler (component/using (new-ring-handler) [:customer-master :orders :product-master]) :web (component/using (new-web-server (Integer. (or (env :http-port) "3000"))) {:handler :ring-handler}))) (defn prod-system [] (dev-system))
  • 15. systems.clj » component/system-map Component SystemMap » component/using Map/Record Vector Inject (component/system-map :customer-master (new-customer-master) :hikari-cp (component/using (new-hikari-cp {:adapter "postgresql" :username "a-project" :password "password" :database-name "a-project" :server-name "localhost" :port-number 5432}) [:migratus]) :migratus (new-migratus {:store :database :migration-dir "migrations" ...
  • 17. product-master.clj (ns a-project-ec.components.product-master (:require [again.core :as again] [cheshire.core :as json] [com.stuartsierra.component :as component] [a-project-ec.retry :as retry] [org.httpkit.client :as http] [schema.core :as s] [slingshot.slingshot :refer [throw+]] [taoensso.timbre :as log]))
  • 18. product-master.clj (def sheetsu-api-url "https://sheetsu.com/apis/v1.0/123456abcde") (def sheetsu-basic-auth-user "a-user") (def sheetsu-basic-auth-pass "a-password") (defn load-product-master [product-master] (again/with-retries retry/http-call-intervals (let [options {:basic-auth [sheetsu-basic-auth-user sheetsu-basic-auth-pass]} {:keys [status headers body error] :as resp} @(http/get sheetsu-api-url options)] (if (or (nil? status) (>= status 300)) (do (log/warn "load-product-master: failed to call sheetsu api." error) (throw+ {:type :rest-api-failure :message error :status status})) (reset! product-master (json/parse-string body true))))) product-master)
  • 19. product-master.clj (defrecord ProductMaster [product-master] component/Lifecycle (start [component] (log/info "Starting ProductMaster...") (assoc component :product-master (load-product-master product-master))) (stop [component] (log/info "Stopping ProductMaster...") (dissoc component :product-master))) (defn new-product-master [] (map->ProductMaster {:product-master (atom nil)}))
  • 20. def ... (defn load-product-master [product-master sheetsu-api-url sheetsu-basic-auth-user sheetwsu-basic-auth-pass] (again/with-retries retry/http-call-intervals (let [options {:basic-auth [sheetsu-basic-auth-user sheetsu-basic-auth-pass]} {:keys [status headers body error] :as resp} @(http/get sheetsu-api-url options)] (if (or (nil? status) (>= status 300)) (do (log/warn "load-product-master: failed to call sheetsu api." error) (throw+ {:type :rest-api-failure :message error :status status})) (reset! product-master (json/parse-string body true))))) product-master) (defrecord ProductMaster [product-master] component/Lifecycle (start [component] (log/info "Starting ProductMaster...") (assoc component :product-master (load-product-master product-master))) (stop [component] (log/info "Stopping ProductMaster...") (dissoc component :product-master))) (defn new-product-master [url user pass] (map->ProductMaster {:sheetsu-api-url url :sheetsu-basic-auth-user user :sheetsu-basic-auth-pass pass :product-master (atom nil)}))
  • 21. systems.clj config :product-master (new-product-master "https://sheetsu.com/apis/v1.0/123456abcde" "a-user" "a-pass")
  • 22. Injection hikari-cp-> orders (ns a-project-ec.systems (:require ... [system.components.hikari :refer [new-hikari-cp]])) :hikari-cp (component/using (new-hikari-cp {:adapter "postgresql" :username "a-project" :password "password" :database-name "a-project" :server-name "localhost" :port-number 5432}) [:migratus]) :orders (component/using (new-orders) [:hikari-cp :product-master :customer-master])
  • 23. Injection orders.clj (ns a-project-ec.components.orders (:require [clj-uuid :as uuid] [com.stuartsierra.component :as component] [a-project-ec.crud :as crud] [a-project-ec.schema.a-project :refer :all] [jdbc.core :as jdbc] [schema.core :as s] [taoensso.timbre :as log]))
  • 24. Injection orders.clj (def salt "12345668-abcd-1111-2222-1a2b3c4d5e6f") (defrecord Orders [hikari-cp product-master customer-master]) (defn new-orders [] (map->Orders {}))
  • 25. Injection orders.clj (s/defn order-item-id :- s/Uuid [order-id :- s/Uuid product-code :- ProductCode] (uuid/v5 order-id product-code)) (s/defn create :- s/Uuid [this :- Orders order :- OrderRequest] (log/info "order-req:" order) (let [{:keys [hikari-cp product-master customer-master]} this order-id (-> (uuid/v1) (uuid/v5 salt) (uuid/v5 (:retailer-id order))) order (-> order (assoc :id order-id) (assoc :order-items (map #(assoc % :id (order-item-id order-id (:product-code %)) :order-id order-id) (:order-items order))))] (jdbc/atomic hikari-cp (let [id (crud/create hikari-cp :orders (dissoc order :order-items))] (for [order-item (:order-items order)] (crud/create hikari-cp :order-items order-item)) id))))
  • 26. Injection crud.clj (s/defn create :- s/Str [conn table :- s/Keyword kv :- {s/Keyword s/Any}] (let [kv (assoc kv :created-at :%now :updated-at :%now) sql (-> (h/insert-into table) (h/values [kv]) (ph/returning :id) sql/format)] (log/debug "create:" sql) (:id (first (jdbc/fetch conn sql)))))
  • 27. Close over » systems.clj :ring-handler (component/using (new-ring-handler) [:customer-master :orders :product-master]) » ring-handler.clj (ns a-project-ec.components.ring-handler (:require [com.stuartsierra.component :as component] [compojure.api.sweet :refer :all] [a-project-ec.routes.customer-master :refer [customer-master-routes]] [a-project-ec.routes.order :refer [order-routes]] [a-project-ec.routes.product-master :refer [product-master-routes]] [ring.util.http-response :refer :all] [schema.core :as s] [taoensso.timbre :as log]))
  • 28. Close over (defmethod compojure.api.meta/restructure-param :components [_ components acc] (update-in acc [:letks] into [components `(::components ~'+compojure-api-request+)])) (defn wrap-components [handler components] (fn [req] (handler (assoc req ::components components)))) (s/defn make-handler [this handler-fn] (wrap-components handler-fn this))
  • 29. Close over (def app (api {:swagger {:ui "/a-project-ec/api-docs" :spec "/a-project-ec/swagger.json" :data {:basePath "/" :info {:title "a-project E-commerce API" :description "API for Cigar Retailers"}}}} customer-master-routes order-routes product-master-routes)) (s/defrecord RingHandler [product-master] component/Lifecycle (start [component] (log/info "Starting RingHandler...") (assoc component :handler-fn (make-handler component #'app))) (stop [component] (log/info "Shutting down RingHandler...") (dissoc component :deps :handler-fn))) (s/defn new-ring-handler [] (map->RingHandler {}))
  • 30. Ring-handler Jetty Inject (ns a-project-ec.components.jetty (:require [a-project-ec.components.ring-handler :as h] [taoensso.timbre :as log] [com.stuartsierra.component :as component] [ring.adapter.jetty :refer [run-jetty]] [schema.core :as s]) (:import (org.eclipse.jetty.server Server)))
  • 31. Ring-handler Jetty Inject (s/defrecord WebServer [port :- s/Int server :- Server handler :- h/->RingHandler] component/Lifecycle (start [component] (log/info "Starting Jetty...") (if (nil? (:server component)) (try (let [handler (:handler-fn handler) server (run-jetty handler {:port port :join? false})] (assoc component :server server)) (catch java.net.BindException e (log/warn e "Jetty has already started.") component)) component)) (stop [component] (log/info "Shutting down Jetty...") (when server (try (.stop server) (catch Throwable t (log/warn t "Failed to stp Jetty."))) (dissoc component :server))))
  • 32. Ring-handler Jetty Inject (defn new-web-server ([port] (map->WebServer {:port port})) ([port handler] (map->WebServer {:port port :handler handler})))
  • 33. compojure-api Component (defroutes order-routes (context "/a-project-ec/api/orders" [] :tags ["Orders"] (POST "/" [] :components [orders] :return OrderId :summary " " :body [order-request OrderRequest] (ok (orders/create orders order-request)))))
  • 34. FAQ » » System » » System Inject » » system.repl/system (:orders system.repl/system) Component
  • 35. Component » (reload) REPL » REPL » » DB ring middleware REPL »