投稿者「たなか」のアーカイブ

node.js + TypeScript でいまどきにふさわしいHelloWorldを

わけあってnode.jsどっぷりな世界に浸からねばならなそう。
とはいえ、素のJavaScriptなど書きたくもない。
せめてECMAScript6は使わせて… おっさんでもクラスくらいは使いたい…
で、ちょっといじってみたけど、やっぱりまだまだねnode.jsのES6対応。
つーことで、MS様のお力を借りて快適にnode.js生活をおくるためにTypeScriptに手を出すことにしたんだ。

まずはhello worldだよね。
せっかくのTypeScriptだし、ムダにモダンに書いてみようとした結果がこちら。

class HelloWorld {
    constructor(message:string) {
        this._message = message;
    }

    private _message:string;

    say():void {
        console.log(this._message);
    }
}

const hello_world = new HelloWorld("こんにちは世界");
hello_world.say();

実にムダにTypeScriptの機能を使いまくってみました感アリアリのhello world。
さて、node.jsくんはこれを実行できるかな?

まずはES5相当でコンパイルして実行。

C:\hogehoge>tsc -t ES5 helloworld.ts

C:\hogehoge>node helloworld.js
こんにちは世界

まあ妥当。

次はみんなお待ちかねのES6だ。

C:\hogehoge>tsc -t ES6 helloworld.ts

C:\hogehoge>node helloworld.js
C:\hogehoge\helloworld.js:1
(function (exports, require, module, __filename, __dirname) { class HelloWorld {

                                                              ^^^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:140:18)
    at node.js:1001:3

残念無念。
まだnode.jsくんにはES6は早過ぎたようだ。
とも思ったが、”use strict”を書いてないからじゃね? と気付いて、最初の行に追加してコンパイル。

C:\hogehoge>tsc -t ES6 helloworld.ts

C:\hogehoge>node helloworld.js
こんにちは世界

よかったよかった。
でもまだいるのか謎の呪文”use strict”…

WordPressのXML-RPCを無効にした話

今日、やたらとブログへのアクセスが多いことに気づき、ついにこのブログもメジャーになったのかと思ったが、単なるXML−RPCへのアタックだった。

185.130.5.209 - - [17/Jan/2016:10:45:49 +0900] "POST /xmlrpc.php HTTP/1.0" 200 695 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

こんなんがいっぱい来てるのねん。
IPアドレスは晒してあげよう。

ウザいし気持ち悪いのでWordPressのXML-RPC自体無効にしてやる。
どうせ使ってないし。

シンプルに.htaccessに以下の記述を追加。

<Files xmlrpc.php>
    order deny,allow
    deny from all
</Files>

ログでエラー返しているのを確認。

185.130.5.209 - - [17/Jan/2016:13:45:55 +0900] "POST /xmlrpc.php HTTP/1.0" 403 470 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

さっさと諦めてね(はーと)

GitHubデビュー(但し使ったことないとは言ってない)

前回、せっかくPythonでSnowflake作ったので、一念発起してGitHubに晒してみた。
実はGitHubに自前のコードを公開するのは初めてだ。
ま、仕事で非公開のレポジトリはガンガン使ってるけどな。

とりあえずユーザー名とレポジトリ名を決めないとだが、ユーザー名はmitakadaiと無駄に主語を大きくしてやった。
レポジトリ名は元の名前がsnowflake(雪片)なんで、ice crystals(雪の結晶)にした。
英辞郎で snowflakes grown from ice crystals (氷の結晶が成長してできた雪片) なんて例文を見付けたからなのはここだけの秘密だ。

ということで、GitHubデビューのURLは
https://github.com/mitakadai/icecrystals
にござるよ。

ユニークID生成方法snowflakeをPythonで書いてみた

ユニークID生成方法としてはUUIDが有名だよね。
基本UUID(version4)で必要十分なんだけど、問題もあって

  1. 128bitもいらない、uint64で扱いたいのに
  2. 完全にランダムなのでソートする意味がない

なんてのがよく出る欠点。
1はまだ我慢しろとか上位or下位64bit使ってなんとかするとか逃げようもある。
しかし2、特に時系列でIDが増加していって欲しいなんてリクエストがあると途端に使えなくなる。
で、RDBMSのオートインクリメント機能使ったり、きちんとロック処理入れてカラムに現在のIDを保持、ID生成するたびにインクリメント、とかやることになる。
それで何が嫌なのって、処理数が増えるとID生成の箇所が間違いなくボトルネックと化す。
処理を軽くしようとmemcachedやredis使った所で単一点なのは変わらず、クラスタ化か? なんて話となり、結構ブルーなのである。
で、なんかUUIDくらいお手軽で、現実的なところでユニーク性が保証できて、おおよそ時系列に沿って値が増加するユニークID生成方が欲しい。
そう思い、google先生に教えを請いた所、snowflakeという生成方法があるそうだ。

snowflakeはTwitterが以前使っていたユニークID生成方法で、かつてはgithubで公開されていたそうだ。
いまでもその残骸は残っている。
https://github.com/twitter/snowflake
生成方法などはこのスライドがわかりやすい。
http://www.slideshare.net/moaikids/20130901-snowflake
簡単に言うと、3つの値からユニークIDを生成する。

  • 最上位bitは0
  • 次の41bitはunix time ミリ秒
  • 次の10bitはあらかじめユニークに割り振ったmachine id
  • 下位12bitは発行する度にインクリメントされていくシリアルナンバー

ぱっと見、必要なユニークID生成が1msで4096ID以下であればユニーク性は守られるであろう。
それで足りないなら、複数マシン/プロセスでmachine idをユニークに割り振って分散すればいい。
さらに、unix timeは通常のepoch(1970-01-01 00:00:00 UTC)ではなく、任意の時刻にセットすることで割り降れるID空間を広げる工夫も入っているようだ。
上位bitがunix timeなので、うまく時系列に並ぶ作りだ。(ミリ秒まで同じタイミングの場合は並ばないケースあり)
最上位bitが必ず0なのでsignedでも安心して使える。
なかなか良い設計に思える。さすがはTwitterだな。
とはいえ、いまは使っていないとのことなので、これでも追いつかなくなったのかID生成。
恐るべしTwitter。

といろいろだらだら書いてきたけど、本題はここから。
この便利なsnowflakeを書いてみたよ、Pythonで。

import time

class Snowflake:

    def __init__(self, machine_id, epoch=0, init_serial_no=0):
        self._machine_id = machine_id
        self._epoch = epoch
        self._serial_no = init_serial_no

    def generate(self):
        unique_id = (
            ((int(time.time() * 1000) - self._epoch) & 0x1ffffffffff) << 22 |
            (self._machine_id & 0x3ff) << 12 |
            (self._serial_no & 0xfff)
            )
        self._serial_no += 1
        return unique_id

def main():
    snowflake = Snowflake(0, epoch=int(time.time() * 1000))
    for i in xrange(100):
        print snowflake.generate()

main()

Snowflakeクラスの使い方など説明するまでもない簡単な作りだ。
実行してみた限り、ちゃんとユニークで連番になってると思う。
まあ、参考程度にどうぞ。
あ、スレッドセーフじゃないので注意ね。

Amazonベーシック ラップトップスリーブ 13.3インチ

いろいろあって、仕事の関係でMacBook Proを持たされることになった。
13インチのRetinaモデル。
薄いわ軽いわSSDのせいかクソ速いわ、今のMacスゲーな。
とはいえ、自分のものではないので、極力丁重に扱わないといけない。
ということで、こんなものをAmazonで買った。

Amazonベーシック ラップトップスリーブ 13.3インチ」だ。
まあ、よくあるノートPC用ソフトケースだ。
最近のAmazonはPB商品にも手を出してるんだ。
MacBook Proを入れてみたけど、きっちりサイズも合っていて、なかなかいい買い物だ。
お値段も898円と、この手のアイテムでは激安と思われる。
しかし、安いからといってクッション性が低い感じはしない。
さすがに高さ1mからコンクリートの床に落下したらアウトだろうけど。
こいつにMacBook Proを入れて、十年来愛用しているポーターのカバンに放り込む予定。

輝くAmazonベーシックロゴ。
ウケ狙いにいいかも。