Posted at

Configuration for Akka application

More than 5 years have passed since last update.

akkaでアプリケーションを作るときに設定値の読み込みをどうするか、という話。


1. akka.actor.Extension

akka.actor.Extension を使って各アクターで共通化させることができる。

import akka.actor.{ExtendedActorSystem, Extension, ExtensionId}

class SampleExtentionImpl(system: ExtendedActorSystem) extends Extension {
val hoge = "HOGE"
}

object SampleExtension extends ExtensionId[SampleExtensionImpl] {
def createExtension(system: ExtendedActorSystem) = new SampleExtensionImpl(system)
}

Extensionを定義しておくことで、アクターから呼び出すことができる。

import akka.actor.Actor

class SampleActor extends Actor {
val ext = SampleExtension(system)

def hoge = ext.hoge //=> "HOGE"
}

手っ取り早い方法ではあるが、ExtensionIdのオブジェクトを直接呼ぶ必要があり、実行時切り替えなどには向かない。

また、Actorクラス以外ではsystem: ActorSystemがないと利用できない。

主にActorSystemにおける共通処理の集約やシングルトンな処理に向いている気がする。


2. TypesafeConfig

akkaはデフォルトでreference.confapplication.confをクラスパスから読み込み、system.settings.configから利用可能にしている。

cf. http://doc.akka.io/docs/akka/2.3.4/general/configuration.html

書式はTypesafeがライブラリとして提供するHOCON(Human-Optimized Config Object Notation)というものになる。

Actorクラスであれば先述したようにsystem.settings.configから取得できるが、他クラスではsystemが無いため利用できない。

直接初期化時の引数に渡すこともできるが、configに依存したクラスであることを明示するため、DIを試みる。

import com.typesafe.config.Config

import akka.actor.ActorSystem

// configを定義するtrait
trait ConfigSupplier {
val config: Config
}

// configから読み込む設定情報の実装
trait DatabaseSetting { this: ConfigSupplier =>
import scala.util.Try
val dbHost = Try(config.getString("sample.db.host")).getOrElse("localhost")
val dbPort = Try(config.getInt("sample.db.port")).getOrElse(5432)
}

// 設定情報を利用するクラス
class SampleApplication { this: DatabaseSetting =>
val connection = getConnection(dbHost, dbPort)
}

object Main extends App {
val system = ActorSystem()

// インスタンス化のときに配線と注入
val app = new SampleApplication with DatabaseSetting with ConfigSupplier {
val config = system.settings.config
}

//...
}