先日発表したChatOps事例のスライドを共有します。
www.slideshare.net
連携のハマりどころ
この発表でちゃんと伝えてないので補足です。
Play2.4で非推奨、かつPlay2.5ではなくなっているGlobalSettingの消し方を紹介します。
なかなか大変なので、ブログにまとめておきました。
Play2.3で書いていたGlobal.scalaのコードを記載します。
object Global extends WithFilters(CsrfFilter, AccessLoggingFilter, SystemAccessFilter) with GlobalSettings with JsonHelper { override def onStart(app: Application) { Akka.system.scheduler.schedule(1 hour, 1 hour) { Image.cleanTempImage() } } override def onError(request: RequestHeader, ex: Throwable): Future[Result] = { Logger.warn(s"Internal server error. Messages : ${e.getMessage} ExceptionMessage: ${e.getMessage()}") } } /** * アクセスログ出力フィルター */ object AccessLoggingFilter extends Filter { import models.component.RequestComponent._ val accessLogger = Logger("access") def apply(next: (RequestHeader) => Future[Result])(request: RequestHeader): Future[Result] = { val resultFuture = next(request) val startTime = System.currentTimeMillis resultFuture.flatMap { result => val takeTime = System.currentTimeMillis - startTime val msg = s"method=${request.method} uri=${request.uri} remote-address=${request.ipAddr} status=${result.header.status} user-agent=${request.userAgent} takeTime=${takeTime} ms" if (takeTime >= 1000) accessLogger.warn(s"*** ${msg} ***") else accessLogger.info(msg) resultFuture } recover { case NonFatal(ex) => { val takeTime = System.currentTimeMillis - startTime val msg = s"method=${request.method} uri=${request.uri} remote-address=${request.ipAddr} status=500 user-agent=${request.userAgent} takeTime=${takeTime}" accessLogger.error(msg) throw ex } } } }
fileを開いて、指定行数の分だけ取得するというロジックを作成していたのですが、
そもそもinputが指定行数以上あるかどうかを知りたかったので、そこもうまく取得できるような実装にする必要がありました。
BufferedReaderで最後の値が、nullになるので、null判定を行うことで、実装。
lisp脳なのか、headとtailでばかり考えていたのですが、
initとlastを使えばうまく実装できたので、メモとして。
ちなみに、aの値は以下のようになるのですが、
val a = Stream(1,2,??)
aの値代入が終わったあとでも以下のようにreader.readLine()を呼ぶと、aの値が変わります。
val reader = new Buffered... val a = Iterator... println(reader.readLine()) print(a)
なぜかは完全には把握していないのですが、Iteratorが遅延して評価しており、aの値が確定する前にreader.readLine()を読んでしまうのだろうということが仮説です。
値クラスを使っていて不可解な挙動があったので、まとめたのとその対処法をメモしておきます。
値クラスとはIntやStringが継承しているAnyValを継承させたクラスです。
一つの値しか持ちませんが拡張メソッドを実装できるため、DDDなどを実現するためのドメインモデルの記述に役立つ記法です。
値クラスと汎用トレイト - Scala Documentation
コンパイル時の型は統一されていますが、実行時の型が不定という問題。
上のように、コンパイル時の内部で保持している型は共にAttributesクラス(値クラス)なのですが、
実際に実行してみると、
ということで、非常に不便な状況です。