前職の同僚諸氏と執筆したクローリングハックという書籍が韓国語に翻訳されたとのことで翔泳社さんから一冊お送りいただきました。
表紙などのデザインモチーフは日本語版ではクモだったのですが、これは…カニ???
まあ、クモがちょっとというのはわかるのですが、いったいなぜカニに…。見た目が似てるからでしょうか。
Scalaで実装されたオープンソースのGitサーバ、GitBucket 4.28.0をリリースしました。
https://github.com/takezoe/gitbucket/releases/tag/4.28.0
プラグインリポジトリからのインストール設定を"System settings"に移動し、HTTPプロキシの設定を行えるようにしました。
今回のバージョンでは以下のような大きなバグをいくつか修正しています。
該当のバグでお困りの場合はアップグレードを検討していただければと思います。修正内容の詳細についてはIssueの一覧をご覧ください。
ScalaベースのフレームワークでクラスのメタデータからSwaggerなどを生成できるものがあるのですが、専用のアノテーションやオブジェクトを使って情報を記述しておく必要があり、特にパラメータの説明などはScaladocに書いたものをそのまま使えればいいのに、と思うことがありました。
そこで試しにScaladocとして記述したコメントを実行時にリフレクションで取得できるようにするコンパイラプラグインを作ってみました。
プロジェクトに以下の設定を追加しておくと使えるようになります。
libraryDependencies += "com.github.takezoe" %% "runtime-scaladoc-reader" % "1.0.1" addCompilerPlugin("com.github.takezoe" %% "runtime-scaladoc-reader" % "1.0.1")
このコンパイラプラグインはコンパイル時にScaladocの内容を@Scaladoc
アノテーションとしてクラスに埋め込みます。たとえば以下のようなクラスがあるとします。
package com.github.takezoe /** * Hello, World! */ class HelloWorld { ... }
このクラスから、実行時に以下のようにしてリフレクションでアノテーションを取得することでScaladocコメントを取り出すことができます。
import com.github.takezoe.HelloWorld import com.github.takezoe.scaladoc.Scaladoc val clazz = classOf[HelloWorld] val scaladoc = clazz.getAnnotation(classOf[Scaladoc]) if(scaladoc != null){ val comment: String = scaladoc.value() println(comment) }
Class
だけでなくMethod
やField
からも同じようにしてScaladocを取得できます。
ただし、/**
から*/
までがそのまま入っているので、実際にデータとして使うにはさらにScaladocをパースしてコメント記号を取り除いたりScaladocタグを抽出したりする必要がありますね。手軽に使えるScaladocパーサがあるとよいのですが…。
正確に言うと自分で作ったのではなく、AirframeというScalaライブラリに相対時間で表記した期間をパースしてくれる機能があるのですが、わけあってこれをJavaにポーティングしてみました。
Maven Centralにdeployしてあるのでpom.xmlに以下の依存関係を追加すれば使えます。
<dependencies> <dependency> <groupId>com.github.takezoe</groupId> <artifactId>jtimewindow</artifactId> <version>1.0.0</version> </dependency> </dependencies>
実際の使い方はこんな感じです。オフセットは基準となる現在日時で、指定しなかった場合はシステム日付が使用されます。期間はZonedDateTime
だけでなくInstant
やエポックタイムで取得することもできます。
import com.github.takezoe.jtimewindow.*; TimeWindowBuilder t = TimeWindow .withTimeZone("PDT") .withOffset("2016-06-26 01:23:45-0700"); TimeWindow w = t.parse("-7d"); ZonedDateTime start = w.getStart(); ZonedDateTime end = w.getEnd();
READMEからの抜粋ですが、以下のような感じで簡潔かつ柔軟な表記が可能です(結果は現在時刻を2016-06-26 01:23:45-0700
に設定した場合の例です)。
Duration | Definition | start | end (exclusive) |
---|---|---|---|
0h |
this hour | 2016-06-26 01:00:00-0700 |
2016-06-26 02:00:00-0700 |
0d |
today | 2016-06-26 00:00:00-0700 |
2016-06-27 00:00:00-0700 |
0M |
this month | 2016-06-01 00:00:00-0700 |
2016-07-01 00:00:00-0700 |
-1h |
last hour | 2016-06-26 00:00:00-0700 |
2016-06-26 01:00:00-0700 |
-1h/now |
last hour to now | 2016-06-26 00:00:00-0700 |
2016-06-26 01:23:45-0700 |
-60m/2017-01-23 01:23:45 |
last 60 minutes to now | 2017-01-23 00:23:00-0700 |
2017-01-23 01:23:45-0700 |
-1d |
last day | 2016-06-25 00:00:00-0700 |
2016-06-26 00:00:00-0700 |
-7d |
last 7 days | 2016-06-19 00:00:00-0700 |
2016-06-26 00:00:00-0700 |
-7d/now |
last 7 days to now | 2016-06-10 00:00:00-0700 |
2016-06-26 01:23:45-0700 |
-3d/2017-04-07 |
last 3 days from a given offset | 2017-04-04 00:00:00-0700 |
2017-04-07 00:00:00-0700 |
+7d |
next 7 days (including today) | 2016-06-26 00:00:00-0700 |
2016-07-03 00:00:00-0700 |
+7d/now |
next 7 days from now | 2016-06-26 01:23:45-0700 |
2016-07-03 00:00:00-0700 |
-1w |
last week | 2016-06-13 00:00:00-0700 |
2016-06-20 00:00:00-0700 |
-1M |
last month | 2016-05-01 00:00:00-0700 |
2016-06-01 00:00:00-0700 |
-1y |
last year | 2015-01-01 00:00:00-0700 |
2016-01-01 00:00:00-0700 |
-1h/2017-01-23 01:00:00 |
last hour to a given offset | 2017-01-23 00:00:00-0700 |
2017-01-23 01:00:00-0700 |
-1h/2017-01-23 01:23:45 |
last hour to a given offset | 2017-01-23 00:00:00-0700 |
2017-01-23 01:23:45-0700 |
GitBucketに以前からGitBucketのバッシュレポートでStackOverflowErrorが発生するというバグレポートが上がっていたのですが、最近直接の知り合いからも言われたので重い腰を上げて修正にトライしてみることにしました。
原因は以下のようなコードで、検索条件をORで繋げている部分が、数が増えるとスタックを食いつぶしてしまうというものでした。
val seq = Range(1, 500) Accounts .filter { t => seq.map { x => t.userId === x.bind } .reduce(_ || _)}.list
実は当時Slickにもイシューを上げてありました。
ただ、このイシューも放置状態ですし、Slickの構造上修正するのも難しそうだったので(ちなみにSlickはクエリビルダで組み立てたASTをSQLにコンパイルして実行するという構造になっているのですが、StackOverflowErrorはASTを組み立てる際ではなく、SQLへのコンパイル時の処理で発生していました)、GitBucket側で以下のようにINを使ったクエリに書き換えることにしました。
Accounts.filter { t => t.userId inSerBind(seq) }.list
これで今までStackOverflowErrorになっていた件数を与えてもとりあえずエラーは起きなくなりました。ただ、条件によっては単純にINに書き換えるとインデックスが効かなくなってしまったり、そもそもINへの書き換えができないケースもあるでしょうし、データベースによってはINで指定可能なパラメータ数に上限もあるので、だいぶやっつけ感のあるワークアラウンドです。
Slickではこういうものは素直にネイティブSQLで記述するべきなのかもしれませんが、せっかく強力なクエリビルダがあるのに肝心な複雑な条件指定が必要な箇所で使えないというのも勿体無い気がするので何か良い解決策があるといいのですが…。
Good morning, my new workplace! pic.twitter.com/b4jEO3jun8
— Naoki Takezoe (@takezoen) 2018年8月1日
Good morning, my new workplace! pic.twitter.com/NZfDYWvHUS
— Naoki Takezoe (@takezoen) 2018年8月9日
トレジャーデータに入社したと思ったらいつのまにかArmに入社していました。
何を言っているのかわからないと思いますが、私もよくわかりませんでした。
Today is my last day at BizReach. I learned a lot of things here. Thanks for exciting days over 4 years! pic.twitter.com/wrPANaxbKW
— Naoki Takezoe (@takezoen) 2018年7月31日
本日、2018年7月31日をもって4年と4ヶ月勤務した株式会社ビズリーチを退職しました。いわゆる退職エントリというもので、誰得な気もしますが自分の振り返りという意味で書いてみたいと思います。
入社しばらくしてから3年ほどはScalaで作っている新規サービスのバックエンドの開発・運用をやっていました。社の誇るスーパーエンジニアや優秀な若者たちと共に新規サービスの立ち上げというエキサイティングな仕事ができたのは大きな刺激になりました。大人数でのScala開発は自分も初めてだったので、もうちょっとこうしておけばよかったなと感じる部分もあった一方で、新規サービスの開発ということで技術以外の部分でいろいろと難しさを感じる部分も多かったです。
その後、サービスの開発からは離れ、ここ1年ほどはApache PredictionIOを始めとしたオープンソース活動にも時間を割くことができました。PredictionIOは業務との絡みもあって関わり始めたものですが、コミッタとしての活動は退職後も続けていきたいと思っています。最近はMLOpsというキーワードも注目を集めていますのでもうちょっと盛り上げていけるといいですね。
開発以外では社内勉強会や渋谷javaの運営、JJUG CCCやScalaMatsuriなど技術系イベントのスポンサー業、登壇や書籍・雑誌記事の執筆なども行なっていました。特に社内勉強会では様々な外部講師の方々に講演をしていただきました。以下のエントリは2015年の分だけですが、この他にも多くの方にお話しいただきました。ご協力いただいた皆さま、本当にありがとうございました。
執筆活動では、以前から一度技術書の翻訳をやってみたいと思っていたのですが、在籍中にScala Puzzlersの日本語版を出すことができ、夢が一つ叶いました。社内の若者たちと本を書いたりできたのもよかったです。
また、Scala Daysなど海外のScalaカンファレンスにも参加することができました。特に2016年のScala Days NewYorkではProgramming in Scala 3rd Editionの原著に小田好先生のサインをいただいたり、昨年はフランスで開催されたScalaIOとイギリスで開催されたScala Exchangeにスピーカーとして登壇させていただいたのはとても良い経験になりました。海外カンファレンスへの参加を通じて英語力の必要性も強く感じました。
振り返ってみると、急成長する未上場企業の様子をCTOでもある上司の傍らから見ることができたのは非常に良い社会勉強になりました。正直いろいろと厳しい部分が多かったですが、これはこれでここでなければできない経験だったと思いますし、今後のキャリアを考える上でも得るものの多い4年間でした。振り返ると個人的に反省すべきと感じる点も多々ありますが、そこも含めて今後に活かしていければと思います。
そんなわけで気づけば私ももうアラフォーだったりするわけですが、まだしばらくはプログラマーとしてやっていきたい気持ちでいますので引き続きよろしくお願いいたします。