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

Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 

Recently uploaded (20)

Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 

リローダブル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 »