u16suzuの blog

日々学んだことのメモブログです。

DBやKVSの楽観ロックと悲観ロックについて調べた

楽観ロック

  • 参照時にロックをしない
  • 仕組み : バージョンを保持しておき、バージョンが更新されていたら、その後の変更は破棄される
  • 同じリソースへの更新が、頻繁に発生しないことを想定したロック
  • 変更が破棄されるためリトライを考慮した設計にしなければならない
  • 主にアプリケーションレベルでかけることが多い
  • Redisではこちらの機能が使える

悲観ロック

  • 参照時にロックをする
  • 仕組み : 参照時にロックをかけ、他のプロセスはそのロックが解放されるまで待ちが発生する
  • 同じリソースへの更新が、頻繁に発生することを想定したロック
  • 主にDBレベルでかけることが多い

参考にしたページ

2016/08/03の日記

このブログ記事に書いてあるスクリプトを読んで、わからないところを調べた。

83億レコードを移行し、日々2,500万レコードのアクセスログをBigQueryに記録している話(インフラ編) | Money Forward Engineers' Blog

set -o pipefail

bashset -o pipefail と書くと、エラーが発生した場合にそれ以降の処理をしないで止まってくれるようになる。

#!/bin/bash -e

set -o pipefail

export LC_ALL=C

ロケール環境変数を指定している。

sortの時に早くなるらしい。

mailコマンドでメールを送る

上のブログの記事とは関係ないけど、mailコマンドに関しても調べた。

mailコマンドを使うと、メールを送ることができる。

本文は以下のように echo文で指定しなければならない。

echo "本文" | mail -s "タイトル"  sample@example.com

2016/8/2(tue)の日記

shell起動時に自動的に指定のディレクトリに移動するようにした。

毎朝仕事を開始する時に、いつも仕事用のディレクトリにcdで移動するのが大変なので書いた。

以下のように .open_directoryディレクトリを指定すると、shell 起動時に移動してくれる。

$ cat ~/.open_directory
/Users/u16suzu/workGithub/rails_project
### 起動時に .open_directory ファイルで指定された directory に自動で移動する
function auto_move(){
  cd "`cat ~/.open_directory`"
}
auto_move

2016/8/1(mon)の日記

プロジェクトで使っている bundler で入れたgemの調査をするためのコマンドをbashで書いた。

Ruby 書くときは atom がメインエディタになりつつある。

RubyMineは重いので、コードリーディングの時だけ使っている。

### bundler でインストールした gem を編集したり、元に戻したりするコマンド
# gem の内部動作を調査する際に使う
# どちらのコマンドも操作対象のgemを引数で指定する必要がある
function gem_edit(){
  atom `bundle show $1`
}
alias gem_edit="gem_edit"
alias gem_restore="bundle exec gem pristine"

ただ、一つだけ問題があって、gemを書き換えた後に rails consoleを再起動しないと読み込んでくれない。

pry

binding.pry を書くと、gemのコードの中で処理を止めてpryで変数の中身を見たりできる。

Arelの定義位置を調べたい時、pryコンソールで show-source Arel とすると、arel のコードがどこで定義されているのかを調査することもできる。

2016/7/31(Sun)の日記

今日はマクドRuby script 用のDSLを書いて遊んだ。

仕事でよく使うテスト用のスクリプトなんだけど、実行するタスクを引数で指定できるようになっている。

それをDSLで指定できるようにした。

@argv = [ {env: "pro"}, 'login', 'start' ]
@env = "dev"

p ARGV

def debug(a)
  puts "---\n#{a}\n---"
end

def before_all(&block)
  @before_all = block
end

def after_all(&block)
  @after_all = block
end

def env(name, &block)
  @env = @argv.select{ |o| o.is_a?(Hash) }.first[:env]
  yield(block) if @env == name
end

before_all do
  debug 'before_all'
end

after_all do
  debug 'after_all'
end

def task(name, &block)
  @before_all.call if @before_all != nil && @argv.include?("all")
  yield block if block_given? && (@argv.include?( name ) || @argv.include?('all') )
  @after_all.call if @after_all != nil && @argv.include?("all")
end

env 'test' do
  debug 'test'
end

env 'stg' do
  debug 'stg'
end

env 'pro' do
  debug 'pro'
end

task 'login' do
  debug 'login'
end

task 'start' do
  debug 'start'
end

task 'finish' do
  debug 'finish'
end

2016/7/28(木)の日記

jbuilderについて

extract! # activerecord objectのアトリビュートを指定して書き出し
ignore_nil! # このメソッドを書いた後は, nil のkey-valueをjsonに書き出さない. ignore_nil! false でオフにできる.

Splat演算子

a, b = *[1,2] # => a = 1, b = 2
*c = 1,2,3 # => c = [1,2,3]

Rubyで、配列を展開するときに使う *array みたいな演算子 * を Splat演算子と呼ぶ.

上の動作は知っていたけど、下の動作は気づいていなかった.

展開後の値を代入で指定しているわけですね.

メソッドの引数にハッシュを指定するときのつまづきポイント

[42] pry(main)> fuga a: 123
=> {:a=>123}
[43] pry(main)> fuga {a: 123}
SyntaxError: unexpected ':', expecting '}'
fuga {a: 123}
[43] pry(main)> fuga( {a: 123})
=> {:a=>123}

メソッドの引数にハッシュを指定したいときに, fuga {a: 123} と書くとエラーになる。

これは、Rubyが引数の { をブロック引数の { として解釈してしまうため発生する。

fuga({a: 123})()明示的に引数指定をすればエラーにならない

はじめ、Splat演算子と関係あるのかなと思ったけど、関係なかった。

今回、仕事で久しぶりに遭遇して、同僚のA氏に昔教えていただいたことを思い出した。

テスト周りで久しぶりにハマった

BaseController の rescue_from で例外の出力処理を書いていなかったため

テストは落ちるけど、スタックトレースが出力されず、原因の特定に困った。

いわゆる例外の握りつぶしに意図せずになってしまっていた。

これから rescue_fromStandardError を補足する場合は注意したい。