ActorでDispatchを使うときHttp.configureは使えなかった
Actorでdispatchを使ってRSSを解析しようとしたら。
dispatchの通常の使い方ではエラーとなったので、残しておく。
dispatchを使う時、dispatch.Http
を作成して利用するのですが。
Actor内では、Http.configure
を使って dispatch.Http
を作ろうとすると上手くいきませんでした。
val executorService = Executors.newFixedThreadPool(10) val httpClient = Http.configure { _.setExecutorService(executorService) .setIOThreadMultiplier(1) .setAllowPoolingConnection(true) .setAllowSslConnectionPool(true) .setConnectionTimeoutInMs(3000) .setRequestTimeoutInMs(10000) .setFollowRedirects(true) .setMaximumConnectionsPerHost(30) }
Http.configure
頼らず、Javaの書き方で対応する。
val executorService = Executors.newFixedThreadPool(10) val asyncHttpClient = new AsyncHttpClient( new AsyncHttpClientConfig.Builder() .setExecutorService(executorService) .setIOThreadMultiplier(1) .setAllowPoolingConnections(true) .setAllowPoolingSslConnections(true) .setConnectTimeout(3000) .setRequestTimeout(10000) .setCompressionEnforced(true) .setFollowRedirect(true).build) val httpClient = new Http(asyncHttpClient)
httpClientが作成できれば、こっちのものなのでいつも通りのdispatchを使い方でおk
val req: dispatch.Req = dispatch.url(url) val r = httpClient(req > (x => x)) val res = r()
Actorのコード全体
class RssActor extends Actor with ActorLogging { private val executorService = Executors.newFixedThreadPool(10) private val asyncHttpClient = new AsyncHttpClient( new AsyncHttpClientConfig.Builder() .setExecutorService(executorService) .setIOThreadMultiplier(1) .setAllowPoolingConnections(true) .setAllowPoolingSslConnections(true) .setConnectTimeout(3000) .setRequestTimeout(10000) .setCompressionEnforced(true) .setFollowRedirect(true).build) private val httpClient = new Http(asyncHttpClient) // private val httpClient = Http.configure { // _.setExecutorService(executorService) // .setIOThreadMultiplier(1) // .setAllowPoolingConnection(true) // .setAllowSslConnectionPool(true) // .setConnectionTimeoutInMs(3000) // .setRequestTimeoutInMs(10000) // .setFollowRedirects(true) // .setMaximumConnectionsPerHost(30) // } def receive = { case msg: String => log.info("start actor") .... } override def postStop() = { log.info("stopped actor") } }
slimでrubyの変数によってクラスを変えるやり方
slimでrubyの変数によってクラスを変えたい時のやり方です。
よくやるやり方が - if
で複数行に渡って書くやり方がある。
- if status == 0 tr.success - else tr.danger
ただ、これだとネストするしこのロジックの後に 同じhtmlを生成しようとすると面倒になる
- if status == 0 tr.success td = hoge td = fuga ... - else tr.danger td = hoge td = fuga ...
これは、嫌だ!!
そこで、1行で綺麗に書く方法が以下の通り。
tr class=(status == 0 ? 'success' : 'danger' )
楽で簡単!!
三項演算子みたいなものです。
docker-machineをupdateした時に出たエラーの対処
docker-machineでdockerを使ってたら、以下のエラーが出たのでその対応!
$ docker ps Error response from daemon: client is newer than server (client API version: 1.21, server API version: 1.20)
docker-machineで作ったサーバをアップグレードすることにしました
docker-machine upgrade [server-name]
$ docker-machine upgrade dev Detecting the provisioner... Upgrading docker... Downloading latest boot2docker iso... Latest release for github.com/boot2docker/boot2docker is v1.9.1 Downloading https://github.com/boot2docker/boot2docker/releases/download/v1.9.1/boot2docker.iso to /Users/oomagaritomohisa/.docker/machine/cache/boot2docker.iso... 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100% Stopping machine to do the upgrade... (dev) Stopping VM... Upgrading machine "dev"... Starting machine back up... (dev) Starting VM... Restarting docker...
docker-machine env
をzshrcでやっていたので新たにtmuxでセッションを開いたら、以下の内容が出ました。
Error checking TLS connection: Error checking and/or regenerating the certs: There was an error validating certificates for host "192.168.99.100:2376": dial tcp 192.168.99.100:2376: i/o timeout You can attempt to regenerate them using 'docker-machine regenerate-certs [name]'. Be advised that this will trigger a Docker daemon restart which will stop running containers.
docker-machine regenerate-certs [server-name]
を実行した
$ docker-machine regenerate-certs dev Regenerate TLS machine certs? Warning: this is irreversible. (y/n): y Regenerating TLS certificates Detecting the provisioner... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon...
うまく、動きました。
バックアップファイルを圧縮してs3に保存するメモ
MySQLのバックアップ
mysqldump -uroot --single-transaction wordpress | gzip | aws s3 cp - s3://backup/wordpress/`date +'%Y-%m-%d'`.gz
個人で利用している分なので mysqldump
で十分な感じです。
mysqldumpしたものを圧縮して s3 に保存するワンライナー
--single-transactionは、ダンプ処理をtransactionで行ってくれます。
画像系のバックアップ
$ tar zcfP - /home/user/backup/ | aws s3 cp - s3://backup/tweet_image/`date +'%Y-%m-%d'`.tar.gz tar: Removing leading `/' from member names
画像系があるフォルダを圧縮してs3に送ります。
tar: Removing leading '/' from member names
は、絶対パスをしていると出る警告みたいです。
オプションの-Pで消せます。
tar: Removing leading `../' from member names - Ask Ubuntu
-
でただひたすら繋げるだけですね。
簡単!!
Playでテスト用の設定ファイルを読み込む(Scala)
毎回、忘れるのでメモとして残しとく
ScalaのPlayでは、以下のように -Dconfig.file=conf/test.conf
で設定しても
デフォルトの application.conf
しか読み込まれません。
activator -Dconfig.file=conf/test.conf test
テスト用の設定を読み込ませたい場合、build.sbtに設定を追加しなければいけない。
in Test
はテストコマンドを実行しているときのみに反映するという設定方法。
javaOptions in Test += "-Dconfig.file=../conf/test.conf"
忘れないためのメモ。
CircleCIでScalaのマルチプロジェクトをテストし、カバレッジを出力する
CircleCIでScalaのプロジェクトのテストを回した時の内容です。
circle.ymlは、以下の通りです。
machine: timezone: Asia/Tokyo java: version: oraclejdk8 dependencies: cache_directories: - "~/.sbt/boot" override: - sbt update test: override: - sbt clean coverage test coverageReport coverageAggregate post: - cp -R ~/hoge/target/scala-2.10/scoverage-report/ $CIRCLE_ARTIFACTS
基本設定
machine: timezone: Asia/Tokyo java: version: oraclejdk8
sbtのバージョンに関して
初めはdependencies
にsbtをダウンロードする内容を記入していたのですが。
dependencies: pre: - wget -q https://dl.bintray.com/sbt/debian/sbt-0.13.8.deb - sudo dpkg -i sbt-0.13.8.deb
リポジトリの内のproject/build.propertiesを見て、
書いてあるsbtのバージョンをインストールしてくれるみたいです。
キャッシュに関して
sbt updateを行う際に利用しているライブラリを毎回ダウンロードするのは、
効率が悪いのでライブラリ関連をキャッシュします。
その設定が以下の部分です。
キャッシュには、sbtのプラグイン系(plugins.sbt)とsbtでダウンロードしたライブラリ(build.sbt)の2種類が必要です。
sbtプラグイン系のキャッシュは ~/.ivy2
の以下にあります。
これは、CircleCI側でデフォルトでキャッシュされるので問題ないです。
もう一つの、sbtでダウンロードしたライブラリのキャッシュは ~/.sbt/boot
にあります。
これは、デフォルトでキャッシュしてくれないので以下のように設定します。
dependencies: cache_directories: - "~/.sbt/boot"
これで、毎回ライブラリ系をダウンロードしなくなるので、大丈夫です。
マルチプロジェクトでのカバレッジの出し方に関して
最後に、カバレッジの出し方です。
scalaでカバレッジを出すプラグインは、sbt-scoverage
を利用しています。
マルチプロジェクトの場合、最後にcoverageAggregate
のコマンドを実行することで
各プロジェクトで出力したレポートをマージしてくれます。
test: override: - sbt clean coverage test coverageReport coverageAggregate
CircleCIは $CIRCLE_ARTIFACTS
という環境変数のパスに
テスト結果のカバレッジのレポートを移動させるといい感じに見れるようにしてくれます。
出力したレポートを$CIRCLE_ARTIFACTS
へコピーすれば完了です。
post: - cp -R ~/hoge/target/scala-2.10/scoverage-report/ $CIRCLE_ARTIFACTS
Continuous Integration and Deployment
いい感じにテストを回せるようになってよかった。
Slick 3.1.0でのCodeGenerator(joda-timeサポート付き)
自分が前に開発したプロジェクトでslickのバージョンが2系を 利用していたのでslick 3系にアップロードした際に CodeGeneratorの書き方が変わっていたので、そのメモです。
slick 2の場合
import com.typesafe.config.{ Config, ConfigFactory } import scala.slick.{ model => m } import scala.slick.codegen.SourceCodeGenerator import scala.slick.driver.JdbcProfile class CustomSourceCodeGenerator(model: m.Model) extends SourceCodeGenerator(model) { override def code = "import com.github.tototoshi.slick.MySQLJodaSupport._\n" + "import org.joda.time.DateTime\n" + super.code override def Table = new Table(_) { override def Column = new Column(_) { override def rawType = model.tpe match { case "java.sql.Timestamp" => "DateTime" case _ => { super.rawType } } } } } object CodeGen { def main(args: Array[String]) { val config: Config = ConfigFactory.load() val slickDriver = "scala.slick.driver.MySQLDriver" val jdbcDriver = config.getString("db.default.driver") val url = config.getString("db.default.url") val user = config.getString("db.default.user") val outputFolder = "lib/src/main/scala/" val pkg = "dilaton.lib" val driver: JdbcProfile = scala.slick.driver.MySQLDriver val db = { driver.simple.Database.forURL(url, driver = jdbcDriver, user = user) } db.withSession { implicit session => new CustomSourceCodeGenerator(driver.createModel()).writeToFile(slickDriver, outputFolder, pkg) } } }
slick 3の場合
import slick.codegen.SourceCodeGenerator import slick.driver.JdbcProfile import scala.concurrent.ExecutionContext.Implicits.global object CodeGenMySQL { def main(args: Array[String]) { val driver: JdbcProfile = slick.driver.MySQLDriver val db = InfrastructureDao.MySQLClient().db val modelAction = driver.createModel(Some(driver.defaultTables)) val modelFuture = db.run(modelAction) val codeGenFuture = modelFuture.map(model => new SourceCodeGenerator(model) { override def code = "import com.github.tototoshi.slick.PostgresJodaSupport._\n" + "import org.joda.time.DateTime\n" + super.code override def Table = new Table(_) { override def Column = new Column(_) { override def rawType = model.tpe match { case "java.sql.Timestamp" => "DateTime" // kill j.s.Timestamp case _ => { super.rawType } } } } }) codeGenFuture.onSuccess { case codeGen => codeGen.writeToFile( "slick.driver.MySQLDriver", "lib/src/main/scala/", "test.lib", "MySQLTables", "MySQLTables.scala" ) } codeGenFuture.onFailure { case e => println("error") e.printStackTrace() } } }