10

ユーザーは最新の動画を含むメールを購読しますが、いつそれらのメールを受け取るかも設定します。

Subscription(user_id, frequency, day, time, time_zone)

user_id  |  frequency  |  day    |  time   |  time_zone
1        |  daily      |  null   |  16:00  |  GMT
2        |  weekly     |  friday |  11:00  |  UTC
3        |  weekly     |  monday |  18:00  |  EST

ユーザーが自分のタイムゾーンで選択した正確な時間と頻度で、失敗することなくメールを送信するにはどうすればよいですか (メールの二重送信や時間の欠落など)。

唯一の頻度は、毎日と毎週です。毎日の場合、その日は null になります。

このためのデータベースとして redis を使用しています。これを正しい方法で行う方法を教えてください。

4

6 に答える 6

2

resque-scheduler gemを使用して fmendez の回答を拡張します。

まず、メールを送信するワーカーを作成しましょう

class SubscriptionWorker
  def self.perform(subscription_id)
    subscription = Subscription.find subscription_id

    # ....
    # handle sending emails here
    # ....

    # Make sure that you don't have duplicate workers
    Resque.remove_delayed(SubscriptionWorker, subscription_id)        

    # this actually calls this same worker but sets it up to work on the next
    # sending time of the subscription.  next_sending_time is a method that
    # we implement in the subscription model.
    Resque.enqueue_at(subscription.next_sending_time, SubscriptionWorker, subscription_id)
  end
end

next_sending_timeサブスクリプション モデルに、次にメールを送信する時間を計算するメソッドを追加します。

# subscription.rb
def next_sending_time
  parsed_time = Time.parse("#{time} #{time_zone}") + 1.day

  if frequency == 'daily'
    parsed_time
  else
    # this adds a day until the date matches the day in the subscription
    while parsed_time.strftime("%A").downcase != day.downcase
      parsed_time += 1.day
    end
  end
end
于 2013-02-23T09:31:35.393 に答える
1

これは、Ruby に固有の問題というよりも、システム レベルの問題です。

まず、すべての時間を GMT として内部に保存します。タイムゾーンは、ビュー内の時間をオフセットする (ユーザーのテーブル内の) プリファレンス設定であることを除けば、実際のものではありません。計算が行われる座標系は一貫している必要があります。

次に、各頻度は、毎日、月曜日、火曜日などの cronjob 設定に対応します。実際には、テーブルのデータから、これが変化していると見なされない限り、2 つの列は必要ありません。

次に、cron が起動したら、スケジューラ ( linux などAT) を使用して、電子メールが送信されたときに処理します。これはシステム レベルのスケジューリングの問題です。少なくとも、システムがこれを処理してくれると信じています。サービスやアプリを含め、システムが再起動された場合を処理する必要があります。

ただし、1 つの注意点として、大量のメールを送信する場合、メールが希望どおりに送信されるという保証はありません。ダンプ/ブロックされないように、実際にはスロットルを戻す必要がある場合があります (たとえば、1000/メッセージが 1 時間に広がります)。ネットワークが異なれば、使用のしきい値も異なります。

だから基本的に:

cron -> at -> メールを送信

于 2013-02-28T18:03:17.727 に答える
0

スケジュールされたタスクの各インスタンスをデータベース テーブルの行として表すDelayedJobまたはResque Gemを使用できます。カレンダーからタスクをトリガー、スケジュール、および撤回するためのメソッドがあります。

于 2013-02-22T18:47:52.620 に答える
0

これを自分のプロジェクトに実装したところです。本当に簡単な方法は、Whenever Gem (こちらhttps://github.com/javan/wheneverにあります) を使用することです。

開始するには、アプリに移動して

gem 'whenever'

次に使用します:

wheneverize .

ターミナルで。これにより、config フォルダーに schedule.rb ファイルが作成されます。

ルールを schedule.rb (以下に示す) に入れ、特定のメソッドを呼び出すようにします。たとえば、私の場合はモデル メソッド DataProviderUser.cron を呼び出します。

このファイルを作成したら、cron ジョブを開始するには、コマンド ラインで次を使用します。

whenever
whenever -w

whenever -c

cron ジョブを停止/クリアします。

github の gems ドキュメントは非常に便利ですが、出力を独自のログ ファイルに設定することをお勧めします (以下で行ったように)。それが役立つことを願っています:)

私のschedule.rbには次のものがあります:

set :output, 'log/cron.log'
every :hour do
runner "DataProviderUser.cron('hourly')"
end

every :day do
runner "DataProviderUser.cron('daily')"
end

every '0 0 * * 0' do
runner "DataProviderUser.cron('weekly')"
end

every 14.days do
runner "DataProviderUser.cron('fortnightly')"
end

every :month do
runner "DataProviderUser.cron('monthly')"
end
于 2013-02-24T11:46:39.567 に答える
0

この目的のためにこの宝石を活用できると思います: https://github.com/bvandenbos/resque-scheduler

よろしく、

于 2013-02-19T18:21:05.337 に答える