Redmine + view customize pluginで連続タスク入力を楽に

Redmineを使い始めたのですが、最初にどんどんタスクを入力したいんだけど、バージョンとか親タスクとか入力が面倒だし、入力を忘れるとガントチャートで変なところに表示されるので、テンポ良く入力できませんでした。 View customize pluginを使って、issue画面に、その次に続くタスクを入力するためのリンクを作ることにしました。versionと親idは同じ、開始日・終了日は前のタスクの終了日をコピーします。関連付けまでしてませんが、できるはず。 Redmineのversionは3.3.0です。

github.com

Futureパターン2

concurrent-rubyをつかうとfutureパターンが、かなりきれいに書ける。

github.com

require 'concurrent-edge'

Concurrent.future {
  raise "exception" if [true, false].sample
  true
}.then {|m|
  puts "succeed #{m}"  # 成功した時の処理、viewになげたり
}.rescue{|m|
  puts "failed #{m}" # 失敗した時の処理
}.then{|m|
  puts "finished" # finalize 
}

sleep 0.1

SlimでHTMLメールを送る

HTMLメールをrubyで送るのにslimテンプレートエンジンを使いたくて。

require 'mail'
require 'slim'

mail = Mail.new do
  from = 'foo@example.net'
  to = 'bar@example.net'
  subject = 'html mail'
end

@name1 = 'Sherlock Holmes'
@name2 = 'John Watson'
mail.html_part = Slim::Template.new('template.slim').render(self)

puts mail.to_s

template.slim

p =@name1 + ' is a private detective'
p =@name2 + ' is his assistant'

Futureパターン

EventMachineでFuture(Promise)パターンするときの例文をメモ

GitHub - cotag/em-promise: A promise/deferred implementation for EventMachine

require 'em-promise'

def testMethod
  deferred = EM::Q.defer
  EM.defer do
    begin
      # databaseなどを非同期処理
      raise "exception" if [true, false].sample # テストなのでわざと例外発生
      deferred.resolve('true') # 成功した時はresolveを実行、引数を渡せる
    rescue => e
      deferred.reject(e) # 例外のときはrejectを実行、引数を渡せる
    end
  end
  deferred.promise # promiseを返す
end

EventMachine.run do
  testMethod.then(proc{|m|
    puts "succeed #{m}" # 成功した時の処理、viewになげたり
  }, proc{|m|
    puts "failed #{m}" # 失敗した時の処理
  }).then(proc{|m|
    puts "finished" # finalize  
    EM.stop
  })
  puts "async"
end

非同期実行なのでasyncが表示されてからtestMethodが、実行されます。 testMethodの中身を、もうすこしすっきり書きたいので、書き直し。

require 'em-promise'

def future
  deferred = EM::Q.defer
  EM.defer do
    yield(deferred)
  end
  deferred.promise
end

def testMethod
  future do |dfr|
    begin
      # databaseなどを非同期処理
      raise "exception" if [true, false].sample # テストなのでわざと例外発生
      dfr.resolve('true') # 成功した時はresolveを実行、引数を渡せる
    rescue => e
      dfr.reject(e) # 例外のときはrejectを実行
    end
  end
end

EventMachine.run do
  testMethod.then(proc{|m|
    puts "succeed #{m}" # 成功した時の処理、viewになげたり
  }, proc{|m|
    puts "failed #{m}" # 失敗した時の処理
  }).then(proc{|m|
    puts "finished" # finalize  
    EM.stop
  })
  puts "async"
end

Exchange serverでメールを送信

Microsoft Exchange serverをつかってrubyからメールを送る方法。みんなActionMailerつかってるけどRailsつかわないときは山ほどgemを入れられるのがつらいので、mail + ruby-ntlmでやる方法をメモ。

require 'mail'
require 'ntlm/smtp'

Mail.defaults do
  delivery_method :smtp, {
    :address              => 'mail.server.com',
    :domain               => 'domain name',
    :user_name            => 'user name',
    :password             => 'password',
    :authentication       => :ntlm,
    :enable_starttls_auto => true
  }
end

Mail.deliver do
  from     'your email address'
  to       'recipients'
  subject  'Hello'
  body     'Test'
end

NVD3.js

綺麗なチャートを表示するのにnvd3.jsを使ってるんだけど、ハマリどころが多いのでメモ。

nvd3.org

追記> こちらにちゃんとしたdocumentがありました。 Nvd3 - reusable charts for D3.js

  • データは各シリーズでx値が一致して抜けがないように。抜けは0やnullで補完する。x値の順序も同じようにソートしておく。
  • chartのx,yメソッドで値のスケーリングや演算ができるが、おかしくなることも多いので、演算済みのデータを渡すのが吉。

    chart.x(function(d) { return d['x'] / 1000 })
    
  • 日付はUnix tampstampをm secでわたす。javascriptで以下のように希望のフォーマットに変換する。

    chart.xAxis.tickFormat(
      function(d) {return d3.time.format('%Y-%m-%d')(new Date(d));});
    
  • 色を変えたいときはjavascriptでcolorをインジェクトしたが、元データに埋め込んでも可。

    data[0]['color'] = '#00cc00';
    
  • グラフのサイズはsvgタグのサイズで指定(slimつかってます)

    div#qty 
      svg style="height:300px; width:100%;"
    
  • 要望: line chartで、ぬけてるポイントは飛ばして線をつなげてほしい。

  • slimのテンプレを貼っておく

      doctype html
      html
        head
          meta charset="utf-8"
          title NVD3.js template
          link href="nv.d3.css" rel="stylesheet"
          script src="d3.min.js"
          script src="nv.d3.min.js"
          javascript:
            d3.json('data.json', function(data) {
              nv.addGraph(function() {
                var chart = nv.models.multiBarChart()
                  .rotateLabels(-45)
                  .margin({top: 30, right: 100, bottom: 100, left: 100});
                chart.multibar.stacked(true);
                chart.xAxis
                     .tickFormat(function(d) {
                       return d3.time.format('%Y-%m-%d')(new Date(d));});
                chart.yAxis
                  .tickFormat(d3.format(',d'))
                  .axisLabel('Number');
                data[0]['color'] = '#00cc00';
                data[1]['color'] = '#ffcc00';
                data[2]['color'] = '#ff9900';
                data[3]['color'] = '#ff3300';
                d3.select('#chart svg')
                    .datum(data)
                    .call(chart);
                nv.utils.windowResize(chart.update);
                return chart;
              });
            });
        body
          span
            h2 style="text-align:center;" Test chart
          div#chart
            svg style="height:300px; width:100%;"
    

AccelTCPで遅延削減

ラズパイVPNサーバの総仕上げとしてAccelTCPでレイテンシーを最小化してみた。 AccelTCPは”プロキシサーバ間のコネクションプーリングにより、TCPコネクションの確立時に発生する3Wayハンドシェイクのオーバーヘッドを削減し、比較的小さなデータのやりとりを行う通信の待ち時間を大幅に短縮できます。”というものです。これで日独間のping 300ms分の遅延を減らすのが目的です。

dsas.blog.klab.org

web browser --> acceltcp:8080 --> (SoftEther VPNでL2TP/IPsec) --> acceltcp:10381 --> squid:3128 --> web site というフローになる。

まず、ラズパイにはsquidをhttp proxyとしてインストールしてポート3128で待機しておく。 キャッシュはいらないので/etc/squid/squid.confで

cache_dir null /tmp

としてディスクキャッシュは無効にしておく。 AccelTCPのbuildは簡単です。

sudo apt-get install libev-dev
git clone git://github.com/KLab/AccelTCP.git
cd AccelTCP
cmake .
make
sudo cp acceltcp /usr/local/bin

まずラズパイにAccelTCPサーバを立てる。AccelTCPは10381で待機します。-4でipv4にするか明示的に自アドレスを書かないとaddress already in useと言われました。バグっぽいです。

acceltcp -q -- --server -4 10381:127.0.0.1:3128

または

acceltcp -q -- --server 127.0.0.1:10381:127.0.0.1:3128

クライアントは自分のmacで下のようにして100本ほどプールを作ります。ラズパイのipは192.168.0.100とします。

acceltcp -q -- -4 --connection-num=100 8080:192.168.0.100:10381

あとはwebブラウザのプロキシを127.0.0.1:8080にすると、日本のサイトへのアクセスは爆速になります。ベンチマークだと1.5倍から2倍弱ですが、体感はもっと速い感じです。webのように小さなファイルをたくさんダウンロードすると効果はてきめんです。http/2が広まるまでは役に立ちそうです。 (googleのdata compression proxyもかなり速い)

ここまでくるとSoftEtherは拠点間接続にして常時つないでおき、AccelTCPもつなぎっぱなしにしておいたほうが使い勝手が良さそうですね。プロキシだけ切り替えればwebへの経路が変わるというのがよさそう。