Bulk Apple 85W Magsafe A1343 MC556J/B

自宅で使っているMacBook Proの電源アダプターが気がついたら、こんな酷い事に。

../../../_images/mbp_power0.png

Apple Storeやヨドバシで普通に購入すると税込みで一万円以上します。高い。 一方、サポート切れていても電源アダプターの場合、Apple Storeに持ち込むと修理費用で交換してもらえた旨の情報も見かけたのですが、それでも一万弱はするようでした。

とAmazonで調べてみたら純正のバルク品が4,280円であったので即購入しました。

届いた品

../../../_images/mbp_power1.png ../../../_images/mbp_power2.png

レビューを事前に確認したら異音がするとか、正規品よりも発熱するとかいうケースも見られたのですが、実際購入して使っている感じでは特にそういうことはなく、発熱も正規品と大差ありません。 唯一違っていたのは、充電中のLEDランプが正規品のそれより小さく見える、というくらいで充電完了時は同じでした。

というわけで結果的には良い買い物でした。

現在は残念ながら

購入したAmazonマーケットプレイスの 店舗では在庫切れですでに取り扱っていない様子 です。

7,000円弱では現在もまだ扱っているところもあるようです。

Third time lucky

matsuu さんから さらにツッコミアドバイス を頂いて 1いくつかコードの修正 を行うことで、正常に http://app.example.org ドメインでドメインのrewriteとカスタムドメイン用のAレコードの設定をせずにアクセスできるようになりました。

matsuu さん、いろいろありがとうございました!

footnote

1

設定はほぼ matsuu さんのGistのまんまなので今回は掲載しません。

Change the reverse proxy upstream of Nginx without Lua

前回の記事(Change the reverse proxy upstream of Nginx by time zone) を見て、 matsuu さん が下記のような設定をGistに掲載されていたので試してみました。

結果、問題なくできたので前回の設定は次のようにシンプルになりました。

map $time_iso8601 $upstream {
    default "app-b.example.org";
    "~T(0|1[01])" "app-a.example.org";
}

server {
    server_name app.example.org;
    rewrite ^ $scheme://$upstream$request_uri permanent;
}

upstream app-a.example.org {
    server app-a.example.net;
}

server {
    server_name app-a.example.org;
    access_log /var/log/nginx/app-a.access.log;
    location / {
        proxy_pass http://app-a.example.org/;
    }
}

upstream app-b.example.org {
    server app-b.example.net;
}

server {
    server_name app-b.example.org
    access_log /var/log/nginx/app-b.access.log;
    location / {
        proxy_pass http://app-b.example.org/;
    }
}

matsuu さん、どうもありがとうございました。

Change the reverse proxy upstream of Nginx by time zone

諸事情 により、VPSでNginxで運用しているリバースプロキシで、下記のように、時間帯によって振り分け先を変更させるようにしてみました。 1

時間の判定には HttpLuaModuleset_by_lua を使いました。nginx-extrasパッケージのインストールが必要です。

$ sudo apt-get install nginx-extras

ここ を参考にNginxに下記の設定を行いました。

(snip)

upstream app-a.example.org {
    server app-a.example.net;
}

server {
    server_name app-a.example.org;
    access_log /var/log/nginx/app-a.access.log;
    location / {
        proxy_pass http://app-a.example.org/;
    }
}

upstream app-b.example.org {
    server app-b.example.net;
}

server {
    server_name app-b.example.org;
    access_log /var/log/nginx/app-b.access.log;
    location / {
        proxy_pass http://app-b.example.org/;
    }
}

server {
    server_name app.example.org;
    access_log /var/log/nginx/app.access.log;
    set $access_a_zone 0;
    set_by_lua $access_a_zone '
        local time = os.date("*t")
        if 0 <= time.hour and time.hour < 12 then
             return 1
        end
    ';

    if ($access_a_zone = 1) {
        rewrite ^ $scheme://app-a.example.org$request_uri permanent;
    }
    rewrite ^ $scheme://app-b.example.org$request_uri permanent;
}

http://app.example.org でアクセスすると、0-11時台は http://app-a.example.net にリダイレクトし、12-23時台は http://app-b.example.net にリダイレクトするだけの設定です。変数access_a_zoneは当初リンク先同様、下記のようにbooleanにしようとしましたが、Ubuntu TrustyのNginx 1.4.6だと期待通りに判定されず、最後のrewriteが実行されてしまうので、0, 1を設定することにしました。

set_by_lua $access_a_zone '
    local time = os.date("*t")
    local access_a_zone = false
    if 0 <= time.hour and time.hour < 12 then
        access_a_zone = true
    end
    return access_a_zone
';

if ($access_a_zone) {
(snip)

カスタムドメインを使う場合、上記の app-a.example.orgapp-b.example.orgCNAME レコードか ALIAS レコードを設定する必要がありますが、今回はリバースプロキシの IPアドレスを app.example.org, app-a.example.org, app-b.example.org それぞれ A レコードとして設定しました。少なくとも現時点ではこの方法でもアクセスできます。

まとめ

リダイレクトしてしまうので、ドメイン名も午前と午後で変わるので、ドメインも変わらないようにするなら app.example.org をリダイレクトし、カスタムドメインをAPIで定時で削除&追加でするとできます。一瞬アクセスできない時間ができてしまいますが。

今のところ解析結果をMemcachedに入れているだけで、特にデータ更新も行わないお遊びのサイトなので今回の方法を取りました。 無料の範囲内で遊ぶために2つもリソース使って、本末転倒じゃないかという内容なので、いろいろお察し下さい…。

footnote

1

制約超えると通知されるメールが増えてきたので…。

Drawing tool of the Python package digraph

ふと Heroku で遊んでみようと思い、 「Webブラウザで Python パッケージの依存関係を表す有向グラフ」を描画するツール を作ってみました。

誰得で、またつまらぬモノを作って公開してしまった、が後悔はしていない。 機能的には個人的には欲しかったモノなのと、最小構成の無料の範囲で遊べているので。

特徴

  • ナビゲーションバーの”Example”をクリックするとpgraphの最新バージョンの依存関係を描画します

  • search packages のフォームから検索すると、 PyPI のAPIでの検索したパッケージ一覧の結果を表示します

  • 描画されたグラフは、ノードをクリックしてドラッグして、グリグリ動かしたり、グラフの拡大・縮小ができます

グリグリ動かす?拡大・縮小?

グラフをグリグリ動かしたり、拡大・縮小するのに使っているのは、 Linkdraw というライブラリです。ご存知でしょうか?

元同僚の mtoshi さんが開発したトポロジを描画するツールで、大統一Debian勉強会 2013発表されました 。ここ数年、一番感銘を受けたソフトウェアで、「mtoshiスゲー!!」を引き起こした一番のシロモノです。

このツールは、ネットワークのトポロジを描画するものなので、今のところ Wiki から辿れる サンプルデモ くらいしか表に出ているものが無いので、他の活用例があると良いなぁと思い、今回使ったという次第です。

pgraphのexample

上記のExampleのリンクから pgraph のグラフを表示すると、pgraph 自体はパッケージの依存関係が多いため、パッケージのノードを動かすとモッサリすることもあります。これはJavaScriptでSVGを処理しているので完全にクライアントのリソース次第です。Linkdraw自体は有向グラフではないので、依存関係の方向性はlineのdescriptionに -> を表示しています。これは py-deps というライブラリで生成しています。Pythonパッケージの依存関係を調べ、各種グラフに変換するために実装したライブラリです。 1

pgraphの構成

Webフレームワークには Pyramid 2 、パッケージの検索、依存関係の分析および Linkdraw用のデータ生成には、自作の py-deps、py-depsに依存関係の分析を実行させる処理は Celery でタスクキューに投げ非同期で実行し、分析した結果はキャッシュに格納します。ローカルで実行する時と、Herokuで実行する時とで、それぞれCeleryのBrokerとキャッシュのバックエンドを変更できるようにしています。

py-depsの機能

パッケージの検索には PyPIの XML-RPC メソッド を使っています。パッケージの依存関係の分析には pip のライブラリを使いました。 3 パッケージによっては、依存パッケージが多く、パッケージのダウンロードに時間が掛かることもあるので、前述の通りCeleryを使っています。キャッシュはPickleでのファイルキャッシュかMemcachedをpy-depsで選べるようにしています。

今回ハマったこと

Herokuでも当初ローカルと同様の構成にしようと、Celeryのバックエンドには CloudAMQP 、キャッシュはPickleでのファイルキャッシュにしていましたが、いろいろ問題がありました。また、Linkdrawでパッケージの依存関係を表示すること自体にも問題がありました。最後にそれらをまとめて紹介します。

Linkdrawでノードとエッジが離れて動いたりする問題

現在のLinkdrawの仕様で一部の使えない文字が原因でした。このため、setuptoolsのextras_requireを表示するのに、 foo[bar]foo____bar と変換しています。

なお、使用できない文字は ドキュメントに追記して おいてもらいました。

celerydが起動しているように見えるのに、タスクが登録されない問題

これは単に、Herokuではworkerがデフォルトでは起動しない、というのを私が知らなかっただけなので、

$ heroku ps:scale worker=1

で起動することで解決しました。

キャッシュファイルが作成されない問題

Herokuではpipでパッケージをインストールできるのだから、アプリから一時ファイルの生成もできるんじゃないか、と誤解していたため、当初依存関係の結果をPickle化してファイルキャッシュとしていました。

しかし、実際に作ってからHeroku上で動かしたところ、ファイルは作成できてもすぐに削除されることを知り、キャッシュのバックエンドには pylibmc を使って、Memcachedを使えるようにしました。 4

HerokuではAddonの Memcached Cloud を使っています。

pylibmcがビルドできない問題

pylibmcは libmemcachedの C bindingのPythonパッケージなので、Herokuで使うには build-pack-python を使ってビルドを行う必要があります。build-pack-pythonは requirements.txt にビルド対象のパッケージが記載されていることをトリガーにして、ビルドを実行します。

で、これでハマりました。

普段、Pythonパッケージを作るとき、requirements.txtはsetup.pyの install_requies から自動生成するようにしています。今回も同様にしていました。しかしこれが原因でpylibmcがビルドされない問題に当たりました。setup.pyでのrequirements.txtの生成は、build-packによるビルドより先に実行されることを期待していました。しかし実際にはbuild-packでのビルドの方が先であり、build-packでのビルド時にはrequirements.txtが無いため、pylibmcがビルドされないということでした。

この問題は、Heroku用のブランチのみrequirements.txtをindexに追加することで解決しました。

CloudAMQPのメッセージがすぐ上限に達しそうな問題

当初、パッケージ依存関係を分析するタスクをCloudAMQPに登録していましたが、タスクの結果を celery.result.AsyncResult でチェックするだけでメッセージカウンターが上がってしまうのでした。。最小構成での無料の範囲で動かそうとすると、CloudAMQPの一ヶ月のメッセージの上限が100万なのに一週間で上限の7割に達してしまいました。これはアカン。

ということで、Celeryのバックエンドを Heroku Postgres に変更することで回避しました。

Heroku Postgresの最小構成の制限はメッセージ数ではなく、1万行までのデータなので、CeleryのBrokerとして使うのであればタスクが正常に完了するか、あるいは失敗してrevokeさせれば、レコードは削除されます。ですのでメッセージ数はもちろん、レコード数の制約も特に気にする必要がありません。

Price planが変わった問題

遊びだしてからSpin downしないように New Relic APM を使って polling していたのですが、なんか Heroku からメールが来るなぁと思ったら、 DynosのPricingが変更されて おり、最低6時間はSleep が必要になっていました。

とりあえず、誰得ツールなので polling するのをやめれば大丈夫でしょう。

終わりに

特にまとめはありませんが、ぜひグリグリ遊んでみてください。

footnote

1

開発自体はpy-depsの方が先です。現状、Linkdrawと NetworkX だけに対応しています。 blockdiag にもそのうち対応する予定です。

2

仕事では Flask, Django および django REST framework が多かったのでたまには別のものも使ってみるか、というノリです。

3

pip コマンドではありません。

4

ローカルで動かす場合にはPickleを使う構成に現在もできます。なお、手元でmemcachedをバックエンドにしてテストするときには、普段yrmcdsをインストールしているのでそっちを使っています。