CompletionStage<T>な変数を同期的に処理したいんですけど〜ってとき
Javaの話です.
CompletionStage<T>を返却するようなメソッドがあって,それを同期的に処理したい (単体テストを書くというシーンが最も多いでしょう) ということが生きているとあります.しかしCompletionStage
はget()
のようなメソッドが生えていないので同期的に処理することができません.thenAccept()
を使おうにも,例えばJUnitのテストケースではすっぽ抜けてしまってうまく扱えません (逆にテストケース以外ではうまく働くでしょう).
そんなときにどうするかというと,手っ取り早い方法はCompletableFuture<T>にキャストしてしまうことでしょう.すると,オブジェクトにget()
が生えてくるので同期的に値を取り扱うことが可能となります.
例:
final CompletionStage<String> completionStage = getSomething(); final CompletableFuture<String> future = (CompletableFuture<String>) completionStage; final String got = future.get(); // ここで同期的に取り扱える
最初からCompletableFuture
で値を返却してほしいですね.以上です.
技術書典7 (く39D) にて「ATコマンドかるた」を頒布します!!!
技術書典7,SORAZINE技術組(く39D
)*1 にて「ATコマンドかるた」を頒布いたします.
「ATコマンドとはなにか?」という疑問については同時に頒布される SORAZINE 技術組 Vol.2019F
中の,おそらく今のところ日本で最も詳しいATコマンドの解説文章をご覧いただければと思いますが *2,その文中から抜粋しますと,
AT コマンドは AT という文字列で始まる、モデムを制御したりするためのテキストベースのコマンド群です.
というものです.ホラ,皆さん生きているとAT+COPS
とかAT+CGDCONT
とかよく見たり喋ったりするじゃないですか? ソレのかるたを頒布するという話です.
こんな感じ:
これがATコマンドふだで……
これが機能ふだです.
たのしい48種類のATコマンドのふだをご用意してございます! (なお,コマンドふだと機能ふだは左上の通し番号で対応が付いています)
ATコマンドふだを読み上げて機能ふだを取るもよし,機能ふだを読み上げてATコマンドふだを取るもよし,ニヤニヤ眺めるのもよしと三方よしな仕上がりとなっております! これで皆さんも遊びながらにしてATコマンドを暗記できます,やりましたね!!!
このようなかわいいパッケージでお出迎え.
ところで,いまのところこのかるたの印刷代を全て建て替えてるので売れないと年を越せません!!!!!!
技術書典7,SORAZINE技術組(く39D
)でお待ちしています!!! よろしくお願いします……
【おわび】
一部ATコマンドふだに誤植がございまして,そちらは大変申し訳ありませんが人力加筆による修正を加えております
(誤)
AT+CCACT
(正: 修正済み)
AT+CGACT
以上です.
Kyoto.なんか #5で「AWS上に構築する メンテ容易なElasticsearch System」というタイトルで話してきました
表題の通りKyoto.なんか #5で話してきました.もうかれこれ3週くらい前の話なのですね……筆不精がたたっております.
内容としてはここ数年ElasticsearchをAWS上で運用しているのでそのアーキテクチャのご紹介という感じの発表をしたという次第です.現状上手いこと回っております.
この発表の後にElasticの@johtaniさんからのメンションで,クラスタまたぎのレプリケーションがElasticsearch 6.7以降サポートされていることを教えていただきました.ありがとうございます!
一応補足。6.7から有償機能だけど、クラスターまたいだレプリケーションあるんです。Elastic Cloudで使えたかはパッとは出てこないけど、、、 https://t.co/89om47nkSF
— Jun Ohtani (@johtani) August 24, 2019
それにつけても最近の願いはAWS Elasticsearch Serviceにauto reshard機能が入ることですね,現場からは以上です.
builderscon 2019見本市 (土曜12時から) で自作ガジェット展示します
id:uzulla, id:mackee_wらと共に自作のE-バッジを展示します!
というかこのブログの内容ママです!!
ここには本物があります.
ぜひお立ち寄りください!!!
ところでチップのデータシートを見ながらあれこれコードを書いて試しているんですが,どうやっても一部機能を実装することが出来ないでいます,これはなんなんだ……当日お立ち寄りの方でお詳しい向きがあれば是非教えていただきたく思います!
よろしくお願いいたします.
tcpdumpで今すぐキャプチャ内容を全部ファイルにflushしてくれ!! というとき
tcpdumpはキャプチャした内容をバッファに蓄積してバッチ的にflushするので,うっかりプロセスを即断するとキャプチャしていた内容をdrainできないことがままあります.困りますね.
Using the SIGUSR2 signal along with the -w flag will forcibly flush the packet buffer into the output file.
というわけでここに書いてあるとおり,SIGUSR2
をtcpdumpのプロセスに対して発行してあげるとその時点のバッファの内容をファイルに吐き出します (ただし -w
フラグによって出力先ファイルを指定している,すなわちファイル書き出しモードにしている必要がある).
If the -w option is specified, make the saved raw packet output ``packet-buffered''; i.e., as each packet is saved, it will be written to the output file, rather than being written only when the output buffer fills.
あるいは -U
(--packet-buffered
) フラグを -w
フラグとともに利用するというのも良いでしょう.ただ,この際はバッファをバイパスして直接ファイルに書き込むような挙動となるので,tcpdumpをdaemonとして常に動かしているような環境ではパフォーマンスの問題が発生する可能性があるので注意が必要そうです.
なお,-B
オプションを使ってバッファサイズを0にするとどうなのか……というとこれは
tcpdump: invalid packet buffer size 0
と出て動きません.なるほど〜,そりゃそうですね.
TypeScriptを使ってアプリケーションの設定ファイルを書く
アプリケーションの設定ファイルと言えばjsonやyamlなんかで書くことが多いと思うんですが,最近はTypeScriptで設定ファイルを書いております.このような感じ:
export interface ApplicationConfig { readonly listenPort: number; readonly timeout: number; readonly apiBaseUrl: string; readonly loggerOptions: LoggerOptions; }
こういう感じで設定のinterfaceを定義しておいて
export class ProductionConfig implements ApplicationConfig { readonly listenPort = 5963; readonly timeout = 5000; readonly apiBaseUrl = "http://internal-api.example.com"; readonly loggerOptions = { level: 'info', }; } // TypeScript (JavaScript) 内で使うなら以下のようにしておくと便利そう (例A) const productionConfig = new ProductionConfig(); export { productionConfig };
というふうに実際の設定を記述するという感じです.
メリットとしては,
- 「何が設定項目なのか」が定義により明らかになる
- 設定漏れが基本的に無い
- これはinterfaceのサポートによるもの
- 型のサポートがある
- 設定の構造化ができる
- 継承が使える
- というかTypeScriptの言語機能を使ったコードが書ける
といったあたりが挙げられると思います.
interfaceの定義によって,「どういった項目が設定されるべきなのか」が「型情報も含めて」明示できるというのは利点の一つと言って良いと思います.
また,ウェブアプリケーションだと例えば本番環境用の設定,ステージング環境用の設定,開発環境用の設定……というふうに複数の設定が存在していることがままあると思うのですが,それぞれの環境のためにinterfaceを満足した設定を記述 (実装) してあげるだけで,漏れが無い (つまりそれぞれが等価な振る舞いをする) 設定を安全に用意することができるようになります.
当然のことながら,設定の実装クラスがinterfaceを実装しきらなかった場合はコンパイルエラーが出るので堅牢です.
型のサポートが得られるというのは言うまでもないですね.安全! 型定義の無い設定を取り扱う際に苦労することがままありましたからね……
あと自分で定義したclassについてもpropertyの型にすることができるので便利です.
個人的には継承が使えるというのは便利ポイントの一つだと思っていまして,例えば「基本的な動作はまったく同じなんだけど一部の機能だけ有効 (あるいは無効) にしたい」みたいなことがあったときに継承は便利に使えるかな〜と思っています.例えばこのような感じ:
export interface ApplicationConfig { readonly port: number; readonly tcpdumpEnabled: boolean; } export class ProductionConfig implements ApplicationConfig { readonly port = 5963; constructor(readonly tcpdumpEnabled: boolean = false) { } } export class ProductionInspectorConfig extends ProductionConfig{ constructor() { super(true); } }
このようにしておくと,基本的には ProductionConfig
と基本的には同じ設定でありながらも, tcpdumpEnabled
を true
にした ProductionInspectorConfig
をお手軽に作れることとなります.
もちろん通常のソフトウェアにおける継承と同じで,is-aとして取り扱える (に等しい) 状況以外で使うと良くないことが起きると思うしそもそも継承を使うと複雑さが容易に増すので,そこは用法用量を守って……という感じでしょう.というかこれはTypeScriptの言語機能を設定記述に使えるという話に過ぎませんね.
あとはTypeScript (JavaScript) 内で使うのならば個別の設定のインスタンスをexportしてしまうか (上記の例A),あるいはinterface側に例えば以下のようなコードを書いて,それによって得られたインスタンスをexportしてしまえば便利そうです:
export interface ApplicationConfig { ... } const appConfig: ApplicationConfig = (() => { const nodeEnv = process.env.NODE_ENV; switch (nodeEnv) { case 'local': return new LocalConfig(); case 'staging': return new StagingConfig(); case 'production': return new ProductionConfig(); default: throw new Error('invalid NODE_ENV: ' + nodeEnv); } })(); export { appConfig };
また,TypeScript以外でこの設定を利用したい,つまり単なる設定記述言語としてこれを利用したい場合は生成した設定インスタンスをJSON.stringify()に食わせてしまえば他の処理系でも取り扱えるJSON形式の設定が得られるのでそのようなスクリプトを書くとポータブル.良いですね.良かった良かった.
と,このような感じでした.TypeScriptは書き味が比較的ライトなので,設定ファイル用途にも書きやすくて良いですね.
systemdで管理しているserviceがopenできるfile descriptorの上限数を増やす
systemdのバージョン
# systemd --version systemd 237
TL;DR
Service
にLimitNOFILE
を設定すると良い.他の特定のリソースについての制限もどうようにかけることが可能です.
ドキュメントは man systemd.exec
で参照できます (ウェブ上はこれが正しいリソース? http://man7.org/linux/man-pages/man5/systemd.exec.5.html).
挙動の検証
現状確認
テストのためにfileを開きまくるperlのscript.ついでにprocのlimit (/proc/{PID}/limits
の中身) も出力する:
#!/usr/bin/env perl use strict; use warnings; use feature qw/say/; open my $fh, '<', "/proc/$$/limits"; say do { local $/; <$fh> }; my @fhs; for (my $i = 0; $i <= 2000; $i++) { my $filename = "/tmp/test.${i}"; open my $fh, ">", $filename or die "$filename: $!"; push @fhs, $fh; }
特に何も考えずにsystemdのservice fileを書いてみます.
[Unit] Description=test [Service] Type=oneshot WorkingDirectory=/tmp/test ExecStart=/usr/bin/perl run.pl [Install] WantedBy=multi-user.target
で,実行してみます
Starting test... Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 3841 3841 processes Max open files 1024 1048576 files Max locked memory 16777216 16777216 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 3841 3841 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us /tmp/test.1020: Too many open files at run.pl line 13, <$fh> line 1. test.service: Main process exited, code=exited, status=24/n/a test.service: Failed with result 'exit-code'. Failed to start test.
Too many open files
で死にます.Max open files
は1024のようですね.ulimit -n
で表示される現状のデフォの値っぽい.
LimitNOFILE
を設定してみる
[Unit] Description=test [Service] Type=oneshot WorkingDirectory=/tmp/test ExecStart=/usr/bin/perl run.pl LimitNOFILE=65536 [Install] WantedBy=multi-user.target
LimitNOFILE=65536
をserviceの設定に追加してみます.それでscriptを実行:
Starting test... Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 3841 3841 processes Max open files 65536 65536 files Max locked memory 16777216 16777216 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 3841 3841 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us
Max open files
が65536になってますね.おかげで実行にも失敗しない! 良かった良かった.
Starting test... Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 3841 3841 processes Max open files 10 10 files Max locked memory 16777216 16777216 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 3841 3841 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us /tmp/test.6: Too many open files at run.pl line 13, <$fh> line 1. test.service: Main process exited, code=exited, status=24/n/a test.service: Failed with result 'exit-code'. Failed to start test.
試しにLimitNOFILE=10
にしてみた様子.逆方向にもちゃんと絞れていることがわかります.