Clojure Camp

一覧に戻る

Duct で Web サーバーを構築しよう

Clojure 製の Web サーバー構築ライブラリとして Duct というものがあります。 この分野については他にも pedestal とか Biff とかいくつかありますが、今回は Duct について話します。

Duct の特徴

  • 関数同士の依存関係を config.edn という設定ファイルに記述することで疎結合にする
  • defmethod をいい感じに使うことで上記を実現している

言ってしまえばこれだけですが、初心者には意味不明でしょうし、ある程度 Web サーバーの設計に詳しい人でないとこのメリットもわかりません。 どんな言語でも課題になるのは関数同士の依存関係、つまり関数の中から他の関数を呼び出すという普通の行為が結構密結合に感じることもあって、そういうのをなんとかできるのが Duct というわけです。 なので、 Rails みたいなフルスタックな Web フレームワークにあるようなデータベースへのアクセスであるとか HTTP リクエストのルーティングの解決であるとかそういう機能は Duct にはありませんし、それが主眼でもありません。

「何を言っているんだお前は」という感じだと思いますので、とりあえず使ってみましょう。

Duct のプロジェクトを用意する

本来なら lein new duct で Duct のプロジェクトを作り始める事ができるのですが、0 からスタートすると手間が多いのである程度作っておきました。 次のリポジトリを見てください。

neumann-tokyo/duct-init

次のような機能を実装済みです

  • PostgreSQL によるデータベースアクセス関係
    • Docker で DB 起動可能
    • hikaricp で connection pool 対応済み
  • database migration
  • metosin/reitit による routing
  • Handler のサンプル
  • Test 用の config.edn とサンプル

このリポジトリを clone したり Fork したりして使ってみてください。

duct-init リポジトリの使い方

Setup

まず homebrewdocker、そして docker compose を使えるようにしておいてください。 homebrew は Linux 環境でも動かすことができるのでインストールをおすすめします (Windows は WSL などの Linux 仮想環境を使ってください)。 リポジトリの中で

./runner setup

をすることで duct-init プロジェクトに必要なツールをインストールします。

duct-init プロジェクトではタスクランナーとして runner というシェルスクリプトを用意しています。 runner の内容を理解する必要はありませんが、興味のある方はコードを読んでみてください。

Database の起動と migration

次のコマンドを実行すると docker compose を使って PostgreSQL が起動します。

./runner up

この状態で別のターミナルで

./runner migrate

を実行してください。 Database の migration と seeds データの読み込みを行います。

migration は db/migrations ディレクトリにあるファイルから実行します。

db
├── migrations
│   ├── 20221023001_init.down.sql
│   └── 20221023001_init.up.sql
└── seeds
    └── dummy_data.sql

db/migrations 以下に [timestamp]_[name].{up,down}.sql のフォーマットでファイルを置いてください。 timestamp の古い SQL から順番に実行してデータベースのテーブルやカラムなどを作成します。

migration を進めるときは ./runner migrate、戻すときは ./runner migrate-down を使います。

seeds データは db/seeds ディレクトリ以下にある SQL ファイルをすべて開発用 DB に対して実行します。 ./runner migrate により seeds データは自動で読み込まれます。

サーバーの起動

準備が整ったのでアプリケーションサーバーを起動してみましょう。 次のコマンドで Leiningen の REPL を起動することができます。

./runner repl

Leiningen は Clojure のパッケージ管理やタスク管理などをできるツールです。 パッケージのインストールが終わると dev という名前空間で REPL が起動します。 ここで、 (go) という関数を実行するとサーバーが 3000 ポートで起動します。

dev=> (go)
:duct.server.http.jetty/starting-server {:port 3000}
:initiated

ファイルの変更をサーバーに反映したい場合は

dev=> (reset)
:reloading (...)
:resumed

または

dev=> (auto-reset)

を使います。

テストの実行

テストを実行するには次のコマンドを使います。

./runner test

引数で名前空間を指定することで特定のテストだけ実行することもできます。

./runner test foo.bar-test

まとめ

今回は neumann-tokyo/duct-init の基本的な使い方を説明しました。 duct の経験が多少ある方はリポジトリのコードを見て活用してみてください。

引き続き、数回にわけて duct の入門記事を公開する予定です。

一覧に戻る