いっきのblog

技術とか色々

pythonを使ってORBとPerceptual Hashで画像の類似度を比べてみる

どうも、くずきです。
今回はPythonを使って画像の類似度を求めました。
なぜやりたいのかというと、インスタグラムなどのSNSで画像を設定していない人を除外したい。つまり、

f:id:kzkohashi:20180105204819j:plain

この画像か、近しい画像を設定している人が見つけ出せれば良い。

比較対象の画像

ファイル名 画像 説明
01.jpg 今回の比較画像
02.jpg f:id:kzkohashi:20180105204927j:plain 女性の画像(インスタから持ってきたのでここではモザイク)
03.jpg f:id:kzkohashi:20180105204924j:plain 男性の画像(インスタから持ってきたのでここではモザイク)
05.jpg f:id:kzkohashi:20180105204819j:plain 比較画像と同じ
06.png f:id:kzkohashi:20180105205044p:plain 比較画像の男風
07.png f:id:kzkohashi:20180105205057p:plain 比較画像の女風
08.png f:id:kzkohashi:20180105205132p:plain 化粧してる風な背景が比較画像に近い
11.jpg f:id:kzkohashi:20180105205448j:plain 背景青い人の画像
12.jpg f:id:kzkohashi:20180105205152j:plain 背景青い人の画像
13.jpg f:id:kzkohashi:20180105205155j:plain 比較画像に少し文字載せたやつ
15.jpg f:id:kzkohashi:20180105205159j:plain 比較画像にかなり文字載せたやつ

ORBを使って類似度を求める

qiita.com

この方の記事の特徴点のマッチングの部分を参考にさせていただきました。
コードはほぼそのままお借りさせていただいたので、結果のみ。

TARGET_FILE: 01.jpg

02.jpg 86.5
03.jpg 76.0
05.jpg 0.0
06.png 57.0
07.png 20.0
08.png 93.0
11.jpg 66.0
12.jpeg 74.5
13.jpg 3.5
15.jpg 59.0

0になれば一致してる画像とみなされている。
06.png15.jpgは除外したかったが思った以上に数値が高くなってしまい、閾値が設定しづらい。同じものが移動したり、回転したりしても特徴点を捉えることで同じものと認識する方法のためこういう結果なのは仕方ない。。

Perceptual Hashを使って類似度を求める

次に、画像をハッシュ値(64bit)に変換して、その距離を測ることによって類似度を求めるPerceptual Hashというアルゴリズムを試してみる。

hideack.hatenablog.com

この方達の記事が参考になる。
Pythonimagehashというライブラリで実装済みのため、それを利用する。

コード

from PIL import Image
import imagehash
import numpy
import scipy
import scipy.fftpack


TARGET_FILE = '01.jpg'
IMG_DIR = '/Users/SayKicho/images/'
target_img_path = IMG_DIR + TARGET_FILE
target_hash = imagehash.average_hash(Image.open(target_img_path))
files = os.listdir(IMG_DIR)

print('TARGET_FILE: %s' % (TARGET_FILE), target_hash)
print('files: %s' % (files))
for file in files:
    if file == '.DS_Store' or file == TARGET_FILE:
        continue

    comparing_img_path = IMG_DIR + file
    try:
        hash = imagehash.average_hash(Image.open(comparing_img_path))
        haming = target_hash - hash
    except cv2.error:
        ret = 100000

    print(file, hash, haming)

比較画像のハッシュ値(target_hash)から比較対象のハッシュ値(hash)を引き算してるところでハミング距離をだしてます。

TARGET_FILE: 01.jpg 00183c18183cffff

02.jpg ffe7c70707010302 51
03.jpg f4e0e9c7c7838330 47
05.jpg 00183c18183cffff 0
06.png 00383c3c18183cff 9
07.png 0018183c18187fff 7
08.png 0018181c1c18183c 16
11.jpg 00000306fcffffff 20
12.jpeg 103f1f8f82c7cfcf 28
13.jpg 00183c18183cffff 0
15.jpg 00181818181cffff 3

一番右がハミング距離。これが0になれば同じ画像と認識される。
さきほどORBのほうで値が高くなってしまった、06.png15.jpgの画像がかなり低く抑えられている。閾値はだいたい10くらいにしておけば近しい画像と認識されそう。

急ぎ足で書いてしまったけど、Perceptual Hashはあくまでも64bitのハッシュ値をもとめるアルゴリズムの総称をいっているので、細かくいうとAverage Hash, Perceptive Hash, Differece Hashなどがある。以下の記事に少し詳しく書いてあるので、気になる方はみとくといいかも。

stmind.hatenablog.com

感想

今回はPerceptual HashAverage Hashが一番効果よかったのでそれを用いて、インスタグラムの設定していない画像を見つけ出すことに成功した。
あまり画像周りに詳しくないので、他のアルゴリズムなども勉強しないとなー。

2017年の振り返りと2018年の抱負

プライベートも含めた振り返りと今年の抱負。

よかったこと

  • 子供生まれた
    • 子育てっていろいろ大変だけどすごく可愛い
    • 自分の時間を自分でコントロールできない感覚に慣れるのに時間かかったなぁ
  • CTOになった
    • フリーランスやめて、四人目の社員としてベンチャー企業に入社
    • イチからプロダクトを立ち上げるのがおもろい
    • 色々な人に手伝ってもらうたびに、色々なコミュニティを大切にしなきゃなぁと思う
  • Reactを初めてさわってリリースした
    • iOSアプリの作りに似てたからすごく作りやすかった
  • キカガクのブラックボックスセミナー受講した
    • 機械学習周りの計算式が結構理解できるようなった。おすすめ
  • 日記を毎日書き続けた
    • 3月からだけど毎日続けた
    • 振り返りしやすいし、頭の整理になるから良い。ブログネタみつかるし。
  • ブログ始めた
    • id:kakku22の教えの元ブログを始めた。
    • 技術の振り返りもできるし、メモとしてもすごくためになってる
    • 調べた情報に+1してあげることで誰かのためになるんだなと思う

よくなかったこと

  • ジムやめた
    • おこづかい制になったので、やめたらめちゃ太った
  • サービス作りにこだわりをもちすぎた
    • 顧客ありきのサービスなのに、それをたまに忘れてしまう
    • そこらへん熱くなりすぎないように、お金を顧客からもらうことについてもっと理解する
  • やりたい技術があんまりできなかった
    • もっと色々挑戦できる部分はあったと思う
    • アウトプット駆動で、しっかり目標立ててやらんといけない
  • LTの発表できなかった
    • 目標にしてたけどやらなかった、もっとやりまする
  • 勉強会ひらけななかった
    • 強い「なぜ」やるのかをしっかりもたないとなぁ

2018年やりたいこと

  • 最高のサービスを作る
    • 2017年はセールスの強い方たちとプロダクトを作りあげるって思った以上に素晴らしいことなんだと実感。
    • セールスとエンジニアの対立ってたまに聞くけど、最高のサービスを作り上げるためにはコラボレーションが重要。そういうチーム作りにしたい。
    • セールス視点からのサービス、エンジニア視点からのサービス、みんな視点のサービス・・・色々な視点を忘れずに作り上げる
  • スマートクリエイティブなエンジニアのチームを目指す
    • "How Google Works"に定義されている自分が最強と思うエンジニアのチーム作りをしたい
    • あんまりそういう方に会ったことないのは、自分がそうじゃないからだから自分も頑張る
    • ビジネス感覚というものをもっと鍛えないといけないきがする
  • Golangでサービス作る
    • 前々から会社として新しいこともやらなきゃいけないと思っていたのもあり、部分的に導入していく
  • ジム再開
    • 会社で契約してもらえるから、復活
    • ムキムキになる
  • 色々なコミュニティと関わりを持つ
    • いろんなコミュニティとの関わり合いは重要だな2017年は感じたので、それをもっと広げる
    • 近しい業種というより、少し離れた業種も面白いかも

感想

なるべく厳選したけど、統一感ないなー。
今年も適度に頑張ろう!!

LaravelでRedshiftを扱う

どうも、くずきです。Lineで「クリスマス」という単語打つたびに背景が変わってイライラしてます。
今回は、LaravelRedshiftを扱う方法についてメモります。

使用しているライブラリは、

  • Laravel 5.5
  • php7.1.1 (phpenv + phpbuild)

[準備] phpenv+php-buildでPostgreSQLのライブラリをいれる

RedsfhitではPostgreSQL JDBC/ODBCに基づいて構築されているため、接続の際にはPostgreSQLの接続のように使える。
自分の環境はphpenv + php-buildphpをすでにインストールしてしまっているため、php-buildを設定後、phpを最近インストールする。

vim ~/.phpenv/plugins/php-build/share/php-build/definitions/7.1.1

上記の設定ファイルに、

configure_option -R "--with-pdo-pgsql"
configure_option -R "--with-pgsql"

を追加する。
-Rを忘れないようにいれておこう。一番ハマったところだけど、以前別の方法でphp環境に似たようなライブラリをいれてたみたく、-Rオプションをつけないせいで上書きしてくれなくてずっとインストールされなかった。。

一応自分の設定全部のせておく。

# 2つ追加
configure_option -R "--with-pdo-pgsql"
configure_option -R "--with-pgsql"

install_package "https://secure.php.net/distributions/php-7.1.1.tar.bz2"
install_xdebug "2.5.0"
enable_builtin_opcache

設定が終わったらいつも通り、

phpenv uninstall 7.1.1
phpenv install 7.1.1
phpenv rehash

とやればインストールされる。

LaravelにRedshiftに接続先情報に追加

config/database.phpconnectionsの項目の中に、redshiftの接続先を追加。
ここらへんはLaravelでの一般的なデータベースの接続と変わらないため細かい説明は割合します。

'redshift' => [
    'driver' => 'pgsql',
    'host' => env('DB_REDSHIFT_HOST', '127.0.0.1'),
    'port' => env('DB_REDSHIFT_PORT', '5439'),
    'database' => env('DB_REDSHIFT_DATABASE', 'forge'),
    'username' => env('DB_REDSHIFT_USERNAME', 'forge'),
    'password' => env('DB_REDSHIFT_PASSWORD', ''),
    'charset' => 'utf8',
    'prefix' => '',
    'schema' => 'public',
    'sslmode' => 'prefer',
],

つづいて、.envにも追加

DB_REDSHIFT_HOST=xxx.ddddd.ap-northeast-1.redshift.amazonaws.com
DB_REDSHIFT_PORT=5439
DB_REDSHIFT_DATABASE=redshift
DB_REDSHIFT_USERNAME=redshift_user
DB_REDSHIFT_PASSWORD=password

LaravelからRedshiftを利用する

Laravelではすでにデータベースのマルチ接続に対応している。以下のリンクが詳しすぎて、そこみたほうがはやい。

fideloper.com

一応自分の使い方を載せておくと、

$users = DB::connection('redshift')->select('SELECT id, name FROM users');

のようにやることで接続している。
Eloquentに紐づけることができるため、できる人はそっちにしたほうが意識せずに使えるためそうしておこう。

まとめ

  • RedshiftはPostgreSQLのドライバで繋がる
  • php-buildの設定ファイルで-Rオプションを忘れずに
  • Eloquentに接続先を紐付けよう

悲しいことに準備のところに一番時間を使ってしまった。。

RedashでTwitter APIを用いて、インフルエンサーの情報を可視化をする

どうも、くずきです。
今日は「Redash Advent Calendar 2017」12日目の記事として、RedashでTwitter APIを用いて、インフルエンサーインサイト情報を可視化をすることをしたいと思います。

qiita.com

インフルエンサーって何やねんって人はすごく簡単にですが以前書いた記事を参考にしてほしい。

kzkohashi.hatenablog.com

これをやるきっかけとしては、マーケティングデータを可視化する「Domo」というツールを使ってインフルエンサーのデータを可視化し、マーケティングツールとして使ってるという情報を聞いたので、、Redashだって!!!と思って書いてます。

[準備] Pythonデータソース機能を使えるようにする

まず事前準備として、Pythonデータソースを使えるようにしておく。
こちらも以前の記事で書いておいたのでそちらを見てほしい。

kzkohashi.hatenablog.com

ツイッターAPIを叩いてみる

まずは、今回使用するPythonのライブラリとして、requests_oauthlibjsonを追加しておこう。
(pip installはしといてください)

f:id:kzkohashi:20171211234524p:plain

次にここでは説明しないが、ツイッターAPIを叩くためのトークンを取得しておき、インフルエンサーであるid:kakaku22のデータを取得してみよう!

twitter.com

from requests_oauthlib import OAuth1Session
import json

CK = 'Consumer Key'                            
CS = 'ConsumerSecret' 
AT = 'Access Token'
AS = 'Access Token Secret'

url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
params = {
    "screen_name": "kakakakakku",
    "exclude_replies": 1,
    "include_rts": 0
    }

twitter = OAuth1Session(CK, CS, AT, AS)
req = twitter.get(url, params = params)

timeline = json.loads(req.text)

for tweet in timeline:
    print(tweet['text'].encode('utf-8'))

f:id:kzkohashi:20171211234547p:plain

色々つぶやいてます。

表示したい情報を集計し、綺麗に表示する

本来は、こんな感じのデータを表示したい。

f:id:kzkohashi:20171211234610j:plain

あんまり見せてはいけない情報すぎて、逆にわかりづらいと思うけど、、
ツイッターだと「フォロワー数」、「平均いいね数」、「平均リツイート数」などが指標となる。
あとは単に集計するだけなので、説明は割愛する。

from requests_oauthlib import OAuth1Session
import json

CK = 'Consumer Key'                            
CS = 'ConsumerSecret' 
AT = 'Access Token'
AS = 'Access Token Secret'

url = "https://api.twitter.com/1.1/statuses/user_timeline.json"
params = {
    "screen_name": "kakakakakku",
    "exclude_replies": 1,
    "include_rts": 0,
    "count": 200
    }

twitter = OAuth1Session(CK, CS, AT, AS)
req = twitter.get(url, params = params)

timeline = json.loads(req.text)

sum_retweet_count = 0
sum_favorite_count = 0
avg_retweet = 0
avg_favorite_count = 0

for tweet in timeline:
    sum_favorite_count = tweet['favorite_count'] + sum_favorite_count
    sum_retweet_count = tweet['retweet_count'] + sum_retweet_count

userInfo = timeline[0]['user']
avg_favorite_count = sum_favorite_count * 1.0/len(timeline)
avg_retweet = sum_retweet_count * 1.0/len(timeline)

result = {}
add_result_row(result, {
    'name': userInfo['screen_name'],
    'follower_count': userInfo['followers_count'],
    'avg_favorite': avg_favorite_count,
    'avg_retweet': avg_retweet
    })
add_result_column(result, 'name', '', 'string')
add_result_column(result, 'follower_count', '', 'integer') # フォロワー数
add_result_column(result, 'avg_favorite', '', 'float') # 平均平均いいね数
add_result_column(result, 'avg_retweet', '', 'float') # 平均平均リツイート数

f:id:kzkohashi:20171211234817p:plain

色々な人のリストとまではいかなかったけど、一人分の情報を表示することができた。

感想

Redash + Twitter APIで簡易ではあるがインフルエンサーのデータの可視化ができた。
次の改善点としては複数人対応や、指定した人のデータを取得できるようにしたらインフルエンサーマーケティングツールとして使えるようになってきそうだ。データの保存とかもできたらいいなぁ。。もう使い方違う気がする。笑

インフルエンサーマーケティングって何だろう Part1

どうも、くずきです。
最初の投稿以外では初めての技術以外の話。

今の会社ではインフルエンサーマーケティングという事業をメインでやってて、基本的にはサービスとシステム面をみることが多い。CEOCOOは事業ドメイン(ここだとインフルエンサーマーケティング)にかなり詳しいが、エンジニアとしての自分はどうだろうか。
サービスを作る上で、言われたことをシステムに落とし込むことだけをしていては良いものを作れないと思っている。事業ドメインを深く知った上で、ビジネスの側面とエンジニアリングを合わせてサービスを構築していくことが理想なんではないかなぁと。良いものの定義とか色々あるのでこの話はまた次のポエムの時に。。。

ということで、頭の中を整理するという意味も込めて書いてみる。

インフルエンサーとは何か

そもそもインフルエンサーって何だろう。
Wikipediaで調べると

インフルエンサー(influencer)は、世間に与える影響力が大きい行動を行う人物のこと。*1

そのまんまの意味だ笑。
じゃあ影響力とはなんだろうか。

他人の考えや行動を変えさせるような力*2

となっている。
俺でいうと誰だろう、、スタートアップ系の話題だとUmada氏とかエリック・シュミット氏の考え方にはだいぶ影響されてると思う。技術面や精神面は近くの人が多くて、先輩であるid:kakku22とか実際によく話す方の影響を受けてる気がする。好き嫌いとか関わらず、ホリエモンやイケハヤ氏なども影響力はあると言える。

ネットやリアルは関係ないしに、影響力をある人を全てさすのだろう。
そう考えると、自分の先輩だって、友達だってある意味インフルエンサーだ。

じゃあインフルエンサーマーケティングとは何だろう

実はWikipediaには続きがあって、

その様な人物の発信する情報を企業が活用して宣伝することをインフルエンサーマーケティングと呼んでいる。

と書かれている。
今までの企業から消費者へのアプローチ方法としては

f:id:kzkohashi:20171210233223p:plain

のように、ダイレクトマーケティングなどが主体となっていた。
インフルエンサーマーケティング

f:id:kzkohashi:20171210233238p:plain

インフルエンサーを通して、消費者(またはコミュニティ)にアプローチする。
なんでまたはコミュニティも含まれてるのかというと、ネット上では消費者に直接というより、ツイッターみたくファンのコミュニティと直接繋がってる場合もあるからだ。

今回はここまでで、次回は「影響力ある人は全てインフルエンサーマーケティングできるのか?」について考える。

1 https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%95%E3%83%AB%E3%82%A8%E3%83%B3%E3%82%B5%E3%83%BC
2 https://kotobank.jp/word/%E5%BD%B1%E9%9F%BF%E5%8A%9B-443069

Redash + docker-composeでPythonデータソースを使うやり方と外部ライブラリを追加する方法

どうも、くずきです。
Redash + docker-composePythonデータソースを扱う場合に、Pythonのライブラリを追加する機会があったのでメモときます。

今回はid:kakku22が提供している、Redashのハンズオンをベースに構築している。

github.com

Pythonデータソースの追加の仕方

ハンズオンを終え「よっしゃPythonデータソースもつかったろ!!」って意気込み、やろうとしたらまさかのデータソースにPythonがなかった。
ぐぐってみると公式に

Data Sources Options and Requirements · Redash Help Center

For security, the python query runner is disabled by default. To enable, add redash.query_runner.python to the REDASH_ADDITIONAL_QUERY_RUNNERS environmental variable. If you used the bootstrap script, or one of the provided images, add to /opt/redash/.env file the line: export REDASH_ADDITIONAL_QUERY_RUNNERS=redash.query_runner.python

セキュリティ上デフォルトオフにしてるから、使いたかったら.envに追加してねとのことだった。

REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.python"

docker-compose.ymlに追加する。全部のせるとみづらいため一部だけのせとく。

  server:
    image: redash/redash:2.0.1.b3080
    command: server
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      REDASH_COOKIE_SECRET: veryverysecret
      REDASH_WEB_WORKERS: 4
      # 追加
      REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.python"
  worker:
    image: redash/redash:2.0.1.b3080
    command: scheduler
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      # 追加
      REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.python"
      QUEUES: "queries,scheduled_queries,celery"
      WORKERS_COUNT: 2
      REDASH_HOST: "http://localhost"

すごいアホだったんだけど、自分はserverの方だけにしか追加してなくて小一時間動かず悩んでました・・。
あとはハンズオン通りに立ち上げると普通にPythonデータソースが使える。

$ docker-compose -f docker-compose.yml up

f:id:kzkohashi:20171209224314p:plain

Pythonの外部ライブラリを追加する

基本的には画像にある、「Modules to import prior to running the script」の項目にPythonで使用したいライブラリ(os, sysなど)をカンマ区切りで追加すればスクリプトを書く時に使用できる。

f:id:kzkohashi:20171209224330j:plain

ただし、外部のライブラリを追加する場合は上記の部分に追加しても使用できない。
調べてみると

github.com

You need to install pandas in the worker container, which actually runs the query.

workerのコンテナにpip installしろってことらしい。
docker-composeでは、commandに追加でスクリプトの実行などができるためそれを利用する。

  server:
    image: redash/redash:2.0.1.b3080
    command: server
    depends_on:
      - postgres
      - redis
    ports:
      - "5000:5000"
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      REDASH_COOKIE_SECRET: veryverysecret
      REDASH_WEB_WORKERS: 4
      REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.python"
  worker:
    image: redash/redash:2.0.1.b3080
    # 追加
    # pip installで追加したいライブラリを入れる。
    command: >
      scheduler && 
      basch -c '
      pip install requests requests_oauthlib
      '
    environment:
      PYTHONUNBUFFERED: 0
      REDASH_LOG_LEVEL: "INFO"
      REDASH_REDIS_URL: "redis://redis:6379/0"
      REDASH_DATABASE_URL: "postgresql://postgres@postgres/postgres"
      REDASH_ADDITIONAL_QUERY_RUNNERS: "redash.query_runner.python"
      QUEUES: "queries,scheduled_queries,celery"
      WORKERS_COUNT: 2
      REDASH_HOST: "http://localhost"

設定後、起動したら他のライブラリと同じくカンマ区切りでモジュールの追加をしたら利用できる。

感想

RedashというよりDockerの方の知識が必要だったなぁ。
ハンズオンにプルリクしようかな。

LaravelのバッチをDiddagで運用したら少し幸せになった話

どうも、くずきです。
弊社の本番環境のバッチはスピード優先で作ったのもあって、処理ごとに分けてはいるものの連携を取ろうとすると以下のことをしなきゃいけない。

  1. 手動で1つ目のバッチを回す
  2. 1つ目が終わったら次のを回す
  3. それが終わったら次を回す・・・

コマンド一つ叩くだけなので、大きな作業は発生しないにしろバッチとバッチの間の無駄な時間やどこまでバッチが終わって、どれくらいかかって、こけた場合はどこでこけたのか・・など色々問題があった。

そこで、Laravelのタスクスケジュール使う手もあったんだけどフローの可視化やリトライ処理を簡単にやりたいと思っていたので、前から良さげだなとおもっていたDigdagを導入してみました。

Digdagとは

あらゆる手動作業を自動化しよう!!というコンセプトで作られたワークフローエンジンです。

github.com

細かい説明は、作成者でもある古橋さんの資料を参考にしましょう。。。

www.slideshare.net

とりあえずいいところとしては、

  1. ymlっぽいやつで簡単にかける
  2. 高可用性な構成にできる
  3. 分散処理できる
  4. テスト段階ながら、UI(可視化など)が提供されている

かなと思う。

既存バッチの把握

まずは、既存バッチを把握する。
Step1 ~ Step4までバッチが分かれており、簡単な図を混ぜながら説明。

  • Step1: 処理したいデータをキューに入れる  
    • sshでログインしてバッチを叩く
    • 3時間前後で終わる

f:id:kzkohashi:20171203230211p:plain

  • Step2: キューに入ってるデータを処理する
    • バックグラウンドで常に動いてるため、特にすることはない
    • 外部のデータに依存するので、長いと数日かかる

f:id:kzkohashi:20171203230250p:plain

  • Step3&4: sshでログイン後Step2のデータを処理する
    • sshでログインしてバッチを叩く
    • 8時間前後で終わる

f:id:kzkohashi:20171203230258p:plain

Digdagへの移行

Digdagのインストールについては今回は省く。
ここに書いてある通りやればすぐ使えると思う。

Getting started — Digdag 0.9.5 documentation

一応載せとく。

$ curl -o ~/bin/digdag --create-dirs -L "https://dl.digdag.io/digdag-latest"
$ chmod +x ~/bin/digdag
$ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc

ちなみに、batch server 1 にインストールしてある。

次にPHPの起動については特に用意はされていないので>shコマンドを使う。

sh>: Shell scripts — Digdag 0.9.5 documentation

このままだとStep2の処理はバックグラウンドで動いてるため、Step3へのフックがない。
そこで、Step2が終わっているかの処理(キューにデータがあるかなど)を行うバッチを追加で書いた。

Step2_task_check

    public function handle()
    {

        $this->line(Carbon::now() . ': start step2_task_check');

        for(;;) {
        
          if (キューの中身があるか)
          {
            // 0を返す
            return config('command.exit_code.SUCCESS');
          }
          sleep(60);
        }


        $this->line(Carbon::now() . ': end step2_task_check');
        
        // 1を返す
        return config('command.exit_code.ERROR');

    }

0 or 1を返すようにすれば、Digdag側で成功か否かを判断してくれる。
ここまで準備したらあとはymlっぽいやつをかけば終わり。

BatchFlow

timezone: UTC

+setup:
  echo>: start ${session_time}

+disp_current_date:
  echo>: ${moment(session_time).utc().format('YYYY-MM-DD HH:mm:ss Z')}

+step1:
  sh>: php /var/www/app/artisan app:step1

+step2:
  sh>: php /var/www/app/artisan app:step2_check

+step3:
  sh>: php /var/www/app/artisan app:step3

+step4:
  sh>: php /var/www/app/artisan app:step4

+teardown:
  echo>: finish ${session_time}

ほぼほぼチュートリアルのままで完成。
特にエラー処理とかDigdagの売りなことは特にしてないんだけど、まずは少し幸せになるという目標だったので自分的にはこれだけでもかなり楽になったし、細かくバッチを作れば組み合わせも楽なので嬉しい。

Digdagに処理をpushする

batch server 1Digdag Serverは起動してある。

digdag push batch_flow

こんな風にpushする。

f:id:kzkohashi:20171203230329p:plain

Digdag UI で起動&確認

Digdag UIDigdagを起動したら勝手に立ち上がっている。
ただ、外向けのポート開けてないっぽいため65432sshのトンネル作って確認する。

ssh -L 8000:localhost:65432 ec2-user@ip -i "~/.ssh/xxx.pem"

その後、pushされた処理があるため、それを起動すれば完了。

終わりに

Digdagの色々良いところは使いきれてないけど、「手動を自動化する」というミッションに関してはすごく簡単にできたので良いと思います。
次くらいまでには、障害に強い構成にしたり、バッチのリラン、Slackへの通知などやる予定。