Skip to content

Support Facebook API in Statistics::Aggregation #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Nov 3, 2017
Merged

Conversation

nalabjp
Copy link
Member

@nalabjp nalabjp commented Oct 29, 2017

#12

Statisctics::AggregationにおいてFacebook APIをサポートしました。
これにより、Facebookイベントの開催履歴を集計することができます。

FacebookのGraph APIはkoala.gem経由で扱います。
dojo_event_servicesテーブルのgroup_idカラムで使用するFacebookのgroup idはlookup-id.comで検索します。
Facebookグループのtopページurlである https://www.facebook.com/[group_name] をlookup-idに入れるとgroup idが返却されるので、db/dojo_event_services.yaml経由で登録しておきます。
(Graph APIで提供されているのかもしれないけど、ちょっと見つけられなかった😢)

TODO

@@ -1,4 +1,4 @@
class DojoEventService < ApplicationRecord
belongs_to :dojo
enum name: %i( connpass doorkeeper )
enum name: %i( connpass doorkeeper facebook )
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

facebookサポートにより追加

@yasulab
Copy link
Member

yasulab commented Oct 29, 2017

👀 ✨

@@ -0,0 +1,9 @@
class IntegerToStringOnGroupIdInDojoEventServices < ActiveRecord::Migration[5.0]
def up
change_column :dojo_event_services, :group_id, :string, null: false
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

facebookのgroup idが15桁なのでintegerからstringに変更した。
bigintにしておくという手もあるが、別のイベントサイトをサポートする際に数値である保証もないので今のうち(?)にstringに変更した。

class IntegerToStringOnServiceGroupIdAndEventIdInEventHistories < ActiveRecord::Migration[5.0]
def up
change_column :event_histories, :service_group_id, :string, null: false
change_column :event_histories, :event_id, :string, null: false
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -20,7 +22,7 @@ def run(dojos, date)

dojos.each do |dojo|
cnps.fetch_events(params.merge(series_id: dojo.dojo_event_service.group_id)).each do |e|
next unless e.dig('series', 'id') == dojo.dojo_event_service.group_id
next unless e.dig('series', 'id').to_s == dojo.dojo_event_service.group_id
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

カラムの型変更に伴いto_sするようにした

@@ -47,7 +49,7 @@ def run(dojos, date)

dojos.each do |dojo|
drkp.fetch_events(params.merge(group_id: dojo.dojo_event_service.group_id)).each do |e|
next unless e['group'] == dojo.dojo_event_service.group_id
next unless e['group'].to_s == dojo.dojo_event_service.group_id
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto


class Facebook
def initialize
@client = Koala::Facebook::API.new(ENV.fetch('FACEBOOK_ACCESS_TOKEN'))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Facebook Graph APIを使うためのaccess tokenは環境変数経由で取得する

namespace :oauth do
desc 'Facebookのaccess tokenを取得します'
task :facebook_access_token, [:app_id, :app_secret] => :environment do |_tasks, args|
puts 'Access Token: ' + Koala::Facebook::OAuth.new(args[:app_id], args[:app_secret]).get_app_access_token
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Facebookのapp_idとapp_secretでaccess tokenを取得するRake task

@nalabjp nalabjp mentioned this pull request Oct 29, 2017
1 task
@nalabjp
Copy link
Member Author

nalabjp commented Oct 30, 2017

Resolved conflicts 4f1b20d

@nalabjp nalabjp changed the title [WIP] Support Facebook API in Statistics::Aggregation Support Facebook API in Statistics::Aggregation Oct 31, 2017
@yasulab
Copy link
Member

yasulab commented Oct 31, 2017

@himajin315 @nanophate お手隙の際にこちらのPRをレビューしてもらえると嬉しいです...!! 🙏

class Facebook
class << self
def run(dojos, date)
fsbk = Client::Facebook.new

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fsbkってfacebookを省略した言葉なんですね🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ローカル変数なので雑に省略しています😅

@@ -113,7 +113,7 @@ def fetch_events(group_id:, since_at: nil, until_at: nil)
limit: 100,
since: since_at,
until: until_at
}.compact!
}.compact
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valueがnilのものがない場合はparamsがnilになってしまうのでbangは不要

@@ -119,7 +119,7 @@ def fetch_events(group_id:, since_at: nil, until_at: nil)

collection = @client.get_object("#{group_id}/events", params)
events.push(*collection.to_a)
while collection.paging['next'] do
while !collection.empty? && collection.paging['next'] do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

collection.empty? == trueの場合、collection.pagingがnilなのでcollectionがemptyかどうかチェックしておく

@yasulab
Copy link
Member

yasulab commented Oct 31, 2017

@nalabjp PRありがとうございます! 😸 ちょっと細かな点ですが、Facebook API の Access Token Key は Travis CI や Heroku にも渡す必要があるかなという認識ですが、既に各環境の環境変数で渡している感じですかね? 🤔 (テストが通っているところを見ると、大丈夫そう?)

あと Facebook の Access Token は確か短期と長期のトークンがあって、60日ごとに更新する必要があったのかなと思うのですが、トークンが Expire された場合って何かしら Rake タスクを手動で走らせる必要があるって認識で大丈夫ですかね? 💭

cf. アクセストークンの有効期限と延長 - Facebook for Developers
https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension

@nalabjp
Copy link
Member Author

nalabjp commented Oct 31, 2017

Facebook API の Access Token Key は Travis CI や Heroku にも渡す必要がある

はい、CIは設定済みですね。
APIのレスポンスにモックを使っている関係で、任意の文字列で良いようになっています。
https://github.com/coderdojo-japan/coderdojo.jp/pull/164/files#diff-354f30a63fb0907d4ad57269548329e3R23
Herokuにはまだ設定していないので、別途設定するか必要な時に取得しにいく必要があります。

トークンが Expire された場合って何かしら Rake タスクを手動で走らせる必要があるって認識で大丈夫ですかね?

はい、今のところその通りです。
access tokenを取得するRake taskは作っておいたので、ひとまずこちらが使えます。
https://github.com/coderdojo-japan/coderdojo.jp/pull/164/files#diff-e895c9dc20985fff884645b79fb7ac96R3

有効期限が切れたケースにまだ遭遇できていないので未実装なのですが、
有効期限切れならリトライしてENVを更新するようにするか、
常に毎回取得しに行くのでも良いかもしれませんね。

@yasulab
Copy link
Member

yasulab commented Oct 31, 2017

Herokuにはまだ設定していないので、別途設定するか必要な時に取得しにいく必要があります。

了解です! 🙆 補足ありがとうございます 😸

常に毎回取得しに行くのでも良いかもしれませんね。

確かに。現在の利用方法で API の利用上限には到達しないと思うので、常に毎回取得・更新する方法が楽で良いかもしれないですね🤔 Document を見ても定期的に (1日1回ぐらい) 更新するような使い方が推奨されていそうです 👀

Facebookのサーバーにリクエストを行う日ごとに、1日に1回更新されます。 リクエストがまったく行われないと、トークンは約60日後に有効期限切れとなり、新しいトークンを取得するために、利用者はログインフローをやり直す必要があります。

https://developers.facebook.com/docs/facebook-login/access-tokens/expiration-and-extension?locale=ja_JP

トークンを更新するRakeタスクについては、Heroku Scheduler で1日1回実行する形でも良いかなと考えているのですが、どうですかね? 🤔 (もし問題がありそうであれば指摘してもらえると嬉しいです 🙏 💦 )

@nalabjp
Copy link
Member Author

nalabjp commented Oct 31, 2017

現在の利用方法で API の利用上限には到達しないと思うので、走らせるたびに更新する方法が楽で良いかもしれないですね

そうしましょうか。
集計のRake task実行時に取得するように変更して、環境変数に入れてしまう事自体をヤメましょうか。
OAuthでトークンを取ればいいだけなので定期的に更新する必要もなさそうに思えました。

@nalabjp
Copy link
Member Author

nalabjp commented Oct 31, 2017

de9841c
access tokenは環境変数に入れず、Rake taskの実行毎に取得するようにしました。
代わりにapp_idとapp_secretを環境変数に入れておく必要があります。(がこちらは固定なので)

@yasulab
Copy link
Member

yasulab commented Nov 1, 2017

MTG MEMO w/ @nalabjp

  • Rakeタスクは冪等 => Heroku Scheduler と組み合わせる (担当: @yasulab)
    • 1日1回 Cron で流す
    • Rate Limit: 300 req / 5min (Doorkeeper)
    • Fetching since 2012 with Retry
  • 失敗するときはイベントサービス単位で失敗するようにする
  • 実行順序に問題があるかもしれないので念のため確認・修正する
    • 現在の実行順序: connpass -> Doorkeeper -> Facebook
  • エラー通知があると便利そうなので実装する

これが終わったら Review & Merge ✅

@nalabjp
Copy link
Member Author

nalabjp commented Nov 2, 2017

  • リトライの範囲を小さく(他のイベントサイトの集計結果に影響しないように) a7da867
  • Rake task終了時にidobataへ通知 cca2f3a
    • 環境変数IDOBATA_HOOK_URLの設定が必要

を実装しました。

1日1回 Cron で流す

MTG時に気付かなかったのですが、月初に一度だけ前月分の集計を実行するようなイメージで実装してました。
日単位で実行できるようになっている方が良いですか?

@nalabjp
Copy link
Member Author

nalabjp commented Nov 2, 2017

a7da867 cca2f3a このあたりの実装、facebookサポートと関係ないので別PRにすれば良かったですね😅

@yasulab
Copy link
Member

yasulab commented Nov 3, 2017

MTG時に気付かなかったのですが、月初に一度だけ前月分の集計を実行するようなイメージで実装してました。
日単位で実行できるようになっている方が良いですか?

@nalabjp Facebook の長期トークンが60日間なので、毎月1回でも大丈夫です! 🙆 ただせっかく Heroku の Hobby プランを使っていて、一日中 Dyno が動いているので、アクセスの少ない夜中とかに (APIの利用制限に引っかからない範囲で) 毎日タスクを流してイベント数が徐々に上がっている感じが見えるとインパクトあって良いかなと思った次第です 🤔💭

とはいえ CoderDojo は週末に行われることが多いので、毎週月曜日に実行する形でも、実質的にはほぼ同じ結果が得られるかなとは考えています ;)

@nalabjp
Copy link
Member Author

nalabjp commented Nov 3, 2017

なるほど、毎週月曜は良さそうですね。
APIを叩く際に月単位で検索しているので、月末が近づくと無駄にレコードの作り直しが発生するなと思った次第です。
特に問題があるわけでもないので、一先ずこのまま運用してみましょうか😁

@yasulab
Copy link
Member

yasulab commented Nov 3, 2017

@nalabjp 他に特に懸念点などなければマージしようと思いますが、いかがでしょう...!! 🤔

特に問題があるわけでもないので、一先ずこのまま運用してみましょうか😁

あ、念のため確認ですが、とりあえずは「毎月1回 (各月の初日) 実行する」という認識で大丈夫ですかね? ✅

@yasulab
Copy link
Member

yasulab commented Nov 3, 2017

.oO(明日 DojoCon Japan 2017 があるので、もし集計が間に合えばそこに滑り込ませたいな的なことを考えています) 😅💭

@nalabjp
Copy link
Member Author

nalabjp commented Nov 3, 2017

あ、念のため確認ですが、とりあえずは「毎月1回 (各月の初日) 実行する」という認識で大丈夫ですかね?

はい、月一でも週一でもどちらでも大丈夫です!

@nalabjp
Copy link
Member Author

nalabjp commented Nov 3, 2017

.oO(明日 DojoCon Japan 2017 があるので、もし集計が間に合えばそこに滑り込ませたいな的なことを考えています) 😅💭

なるほど、ひとまずコンフリクトだけ直してしまうので少々お待ち下さい。

@nalabjp
Copy link
Member Author

nalabjp commented Nov 3, 2017

@nalabjp 他に特に懸念点などなければマージしようと思いますが、いかがでしょう...!! 🤔

CI通ったのでマージしてしまいます! 💪

@nalabjp nalabjp merged commit 0db4314 into master Nov 3, 2017
@nalabjp nalabjp deleted the support-facebook-api branch November 3, 2017 05:40
@yasulab
Copy link
Member

yasulab commented Nov 3, 2017

ありがとうございます! 😸

@yasulab yasulab added the 統計情報 Tracking event record function via APIs: https://coderdojo.jp/stats label Jan 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
統計情報 Tracking event record function via APIs: https://coderdojo.jp/stats
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants