newしてもObjectの参照が解除されないシーンがある

  • prototypeで宣言されたオブジェクトをconstructorで初期化していない
  • 直接値を挿入せず、キーのみを読み書きする

以上の条件がそろうとnewしてもオブジェクトの参照は解除されず、すべてのインスタンスで同じオブジェクトを共有することになる

うまく利用できればかっこいい実装できそうだけど、人類にはまだ早い感じがするので大人しく気をつけることにする。


自動でソートしてくれるBackbone.Marionette.CompositeView

Backbone.Marionette.CompositeViewの挙動を、prototypeを拡張することで自動でソートして挿入してくれるようにした。coffeeでは.prototype.::と記述できる。

このセクション以降で定義されたCompositeViewにBackbone.Collection::comparator()の定義されたcollectionをattachすれば、Collectionのソートオーダーに従ってレンダリングしてくれる。中間に挿入されたものでも$.eq比較で適切に挿入される。

↓ 実装自体はここ

https://github.com/marionettejs/backbone.marionette/wiki/Adding-support-for-sorted-collections


mdadmが止まった後にやったこと

ある日帰ったらサーバが止まってた。何事かと思いディスプレイをつないでみたらGRUBの起動で止まってた。

キーボードを接続して通常起動すると、どうやらmdadmで組んでるRAID10からディスクが2枚外れてしまい、マウント不可状態に陥っていたらしいことがわかった。後からわかったことだが、ディスクは壊れていなかった。

日常では感じることのできない胸の高鳴りに冷や汗を流しながら、恋をしたような気分でディスプレイと向き合った。以下、mdadmちゃんとの文通ログ。


まずはsshできるようにした

/homeがロストしてしまっていたので公開鍵は使えない、直接sshd_configを編集してPermitPasswordLoginをyesに、sshできるようにした

ssh後、まずは状況の確認、mdstatとdetailでmdの状態を確認する

$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md0 : inactive sdd[2] sde[3] sdf[4] sdg[7]
      11720542048 blocks super 1.2

unused devices: <none>
$ mdadm --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Mon Dec  3 01:05:01 2012
     Raid Level : raid10
  Used Dev Size : -1
   Raid Devices : 6
  Total Devices : 4
    Persistence : Superblock is persistent

    Update Time : Wed Jun  4 00:29:50 2014
          State : active, FAILED, Not Started 
 Active Devices : 4
Working Devices : 4
 Failed Devices : 0
  Spare Devices : 0

         Layout : near=2
     Chunk Size : 1024K

           Name : ubuntu:0
           UUID : 5715dcea:bb512ad2:15f0c995:a1e21b5b
         Events : 36178

    Number   Major   Minor   RaidDevice State
       0       0        0        0      removed
       1       0        0        1      removed
       2       8       48        2      active sync   /dev/sdd
       3       8       64        3      active sync   /dev/sde
       4       8       80        4      active sync   /dev/sdf
       7       8       96        5      active sync   /dev/sdg

どうやらsdbとsdcが落ちている模様(。ŏ﹏ŏ。)

$ mdadm --examine /dev/sdb
/dev/sdb:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : 5715dcea:bb512ad2:15f0c995:a1e21b5b
           Name : ubuntu:0
  Creation Time : Mon Dec  3 01:05:01 2012
     Raid Level : raid10
   Raid Devices : 6

 Avail Dev Size : 5860271024 (2794.40 GiB 3000.46 GB)
     Array Size : 8790405120 (8383.18 GiB 9001.37 GB)
  Used Dev Size : 5860270080 (2794.39 GiB 3000.46 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : active
    Device UUID : 4c920d09:40a0ecb9:b65b5bf2:6e466ed7

    Update Time : Tue Jun  3 20:58:42 2014
       Checksum : e13e4087 - correct
         Events : 35176

         Layout : near=2
     Chunk Size : 1024K

   Device Role : Active device 0
   Array State : AAAAAA ('A' == active, '.' == missing)
$ mdadm --examine /dev/sdc
/dev/sdc:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : 5715dcea:bb512ad2:15f0c995:a1e21b5b
           Name : ubuntu:0
  Creation Time : Mon Dec  3 01:05:01 2012
     Raid Level : raid10
   Raid Devices : 6

 Avail Dev Size : 5860271024 (2794.40 GiB 3000.46 GB)
     Array Size : 8790405120 (8383.18 GiB 9001.37 GB)
  Used Dev Size : 5860270080 (2794.39 GiB 3000.46 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : active
    Device UUID : 78d5a2df:c46b0a98:d8a27284:3047a3e9

    Update Time : Wed Jun  4 00:27:01 2014
       Checksum : 3a3ed14a - correct
         Events : 36170

         Layout : near=2
     Chunk Size : 1024K

   Device Role : Active device 1
   Array State : .AAAAA ('A' == active, '.' == missing)

壊れているわけではなさそうな雰囲気٩(ˊᗜˋ*)و

$ smartctl -a /dev/sdb
(中略)
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
(以下略)

SMARTは大丈夫だったので追加してみる

$ mdadm --re-add /dev/md0 /dev/sdb
mdadm: --re-add for /dev/sdb to /dev/md0 is not possible

(⑅☍﹏⁰)

一回止めてassembleする

$ mdadm --stop /dev/md0
mdadm: stopped /dev/md0
$ mdadm --assemble --run --force /dev/md0 /dev/sd[bcdefg]     
mdadm: forcing event count in /dev/sdc(1) from 36170 upto 36178
mdadm: /dev/md0 has been started with 5 drives (out of 6).

sdcが追加できた

$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md0 : active raid10 sdc[1] sdg[7] sdf[4] sde[3] sdd[2]
      8790405120 blocks super 1.2 1024K chunks 2 near-copies [6/5] [_UUUUU]

unused devices: <none>

sdbを追加して確認してみる

$ mdadm /dev/md0 --add /dev/sdb                          
mdadm: added /dev/sdb
$ cat /proc/mdstat
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md0 : active raid10 sdb[6] sdc[1] sdg[7] sdf[4] sde[3] sdd[2]
      8790405120 blocks super 1.2 1024K chunks 2 near-copies [6/5] [_UUUUU]
      [>....................]  recovery =  0.0% (404736/2930135040) finish=482.5min speed=101184K/sec

unused devices: <none>

復旧作業に入った ヾ(❀╹◡╹)ノ゙

一応examineを確認してみる

$ mdadm --examine /dev/sdb
/dev/sdb:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x2
     Array UUID : 5715dcea:bb512ad2:15f0c995:a1e21b5b
           Name : ubuntu:0
  Creation Time : Mon Dec  3 01:05:01 2012
     Raid Level : raid10
   Raid Devices : 6

 Avail Dev Size : 5860271024 (2794.40 GiB 3000.46 GB)
     Array Size : 8790405120 (8383.18 GiB 9001.37 GB)
  Used Dev Size : 5860270080 (2794.39 GiB 3000.46 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
Recovery Offset : 0 sectors
          State : clean
    Device UUID : 574e70b2:38c28301:a1586a47:11250489

    Update Time : Wed Jun  4 01:49:14 2014
       Checksum : d8dd47a5 - correct
         Events : 36188

         Layout : near=2
     Chunk Size : 1024K

   Device Role : Active device 0
   Array State : AAAAAA ('A' == active, '.' == missing)
$ mdadm --examine /dev/sdc
/dev/sdc:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x0
     Array UUID : 5715dcea:bb512ad2:15f0c995:a1e21b5b
           Name : ubuntu:0
  Creation Time : Mon Dec  3 01:05:01 2012
     Raid Level : raid10
   Raid Devices : 6

 Avail Dev Size : 5860271024 (2794.40 GiB 3000.46 GB)
     Array Size : 8790405120 (8383.18 GiB 9001.37 GB)
  Used Dev Size : 5860270080 (2794.39 GiB 3000.46 GB)
    Data Offset : 262144 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : 78d5a2df:c46b0a98:d8a27284:3047a3e9

    Update Time : Wed Jun  4 01:49:14 2014
       Checksum : 3a3de4a3 - correct
         Events : 36188

         Layout : near=2
     Chunk Size : 1024K

   Device Role : Active device 1
   Array State : AAAAAA ('A' == active, '.' == missing)

大丈夫そう(๑・◡・)

これでダメなら予備ディスクと交換する


javascriptで発生するイベントを間引く

近辺で話題になっていたのでまとめた。

イベントを律儀に全て処理しているとattachした即時関数が過剰に実行されてしまう。API通信が大量に発生したり、処理落ちが発生したりする。

lodashunderscoreに実装されている_.throttle_.debounceというファクトリを利用することで、これらをスマートに解決できる。

_.throttle

設定した時間内に2回以上実行されない関数を返すファクトリ。スクロールイベントのような連続量を間引くのに利用される。

$el = $ '#header'
($ window).on 'scroll', ->
  $el.css top: ($ document).scrollTop()

scrollに同期してヘッダを追従させたりする場合、scrollの全フレームを処理しなければいけないような気になる。

しかし、scrollイベントの全フレームを処理しないとカクカクして見えるほど人類のステージは高くない。

$el = $ '#header'
($ window).on 'scroll', _.throttle (event) ->
  $el.css top: ($ document).scrollTop()
, 12

これで「どれだけ実行しても12秒に1回しか実行できないようにラッピングされた」即時関数がscrollにattachされる。

何かをスクロールに同期する場合、12ミリ秒くらいだと殆ど気にならなかった、24くらいまで増やすと結構気になった。

「だいたい41ミリ秒で24fpsだから41でいいじゃん」と思ったけど元のscrollイベントがアナログ値ではないのでそんなことは全く無かった。

入ってきた連続量の頭を評価しない({ leading: false })、ケツを評価しない({ trailing: false })等のオプションがある。詳しくはドキュメントを参照の事。

_.debounce

実行するとタイマーをリセットしてabort、タイマーが切れると実行される関数を返すファクトリ。

($ '#input').on 'keyup', (event) ->
  $el = $ event.currentTarget
  $.ajax '/api/search',
    data: name: $el.val()
    dataType: 'json'
  .done (json) ->
    $el.val json.name if json.name

こんな即時関数を実装してAPIアクセスが大量に発生し、慌ててsetTimeoutで遅延実行するような機構を実装した経験が誰にでもあると思う。

でもdebounceがあればもう慌てる必要は無い。

($ '#input').on 'keyup', _.debounce (event) ->
  $el = $ event.currentTarget
  $.ajax '/api/search',
    data: name: $el.val()
    dataType: 'json'
  .done (json) ->
    $el.val json.name if json.name
, 240

これで「最後に実行されてから240ミリ秒以内にもう一度実行されたらabort、実行されなければexec」する即時関数がkeyupにattachされる。


1 2 3 4 5