Permalink
Browse files

Add TryLater: a system for scheduling events.

  • Loading branch information...
1 parent 44a8dd6 commit 89762c93f0834a165c29128896b9b2075e099fb0 Roger Ostrander committed with spladug Feb 10, 2014
Showing with 116 additions and 0 deletions.
  1. +1 −0 install-reddit.sh
  2. +60 −0 r2/r2/models/trylater.py
  3. +43 −0 scripts/trylater.py
  4. +12 −0 upstart/reddit-job-trylater.conf
View
1 install-reddit.sh
@@ -595,6 +595,7 @@ if [ ! -f /etc/cron.d/reddit ]; then
* * * * * root /sbin/start --quiet reddit-job-email
*/2 * * * * root /sbin/start --quiet reddit-job-broken_things
*/2 * * * * root /sbin/start --quiet reddit-job-rising
+0 * * * * root /sbin/start --quiet reddit-job-trylater
# jobs that recalculate time-limited listings (e.g. top this year)
PGPASSWORD=password
View
60 r2/r2/models/trylater.py
@@ -0,0 +1,60 @@
+# The contents of this file are subject to the Common Public Attribution
+# License Version 1.0. (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
+# License Version 1.1, but Sections 14 and 15 have been added to cover use of
+# software over a computer network and provide for limited attribution for the
+# Original Developer. In addition, Exhibit A has been modified to be consistent
+# with Exhibit B.
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+# the specific language governing rights and limitations under the License.
+#
+# The Original Code is reddit.
+#
+# The Original Developer is the Initial Developer. The Initial Developer of
+# the Original Code is reddit Inc.
+#
+# All portions of the code written by reddit are Copyright (c) 2006-2014 reddit
+# Inc. All Rights Reserved.
+###############################################################################
+
+import contextlib
+import datetime
+
+from pycassa.system_manager import TIME_UUID_TYPE
+
+from r2.lib.db import tdb_cassandra
+
+
+class TryLater(tdb_cassandra.View):
+ _use_db = True
+ _read_consistency_level = tdb_cassandra.CL.QUORUM
+ _write_consistency_level = tdb_cassandra.CL.QUORUM
+ _compare_with = TIME_UUID_TYPE
+
+ @classmethod
+ def multi_ready(cls, rowkeys, cutoff=None):
+ if cutoff is None:
+ cutoff = datetime.datetime.utcnow()
+ return cls._cf.multiget(rowkeys,
+ column_finish=cutoff,
+ column_count=tdb_cassandra.max_column_count)
+
+ @classmethod
+ @contextlib.contextmanager
+ def multi_handle(cls, rowkeys, cutoff=None):
+ if cutoff is None:
+ cutoff = datetime.datetime.utcnow()
+ ready = cls.multi_ready(rowkeys, cutoff)
+ yield ready
+ for system, items in ready.iteritems():
+ cls._remove(system, items.keys())
+
+ @classmethod
+ def schedule(cls, system, data, delay=None):
+ if delay is None:
+ delay = datetime.timedelta(minutes=60)
+ key = datetime.datetime.utcnow() + delay
+ cls._set_values(system, {key: data})
View
43 scripts/trylater.py
@@ -0,0 +1,43 @@
+# The contents of this file are subject to the Common Public Attribution
+# License Version 1.0. (the "License"); you may not use this file except in
+# compliance with the License. You may obtain a copy of the License at
+# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public
+# License Version 1.1, but Sections 14 and 15 have been added to cover use of
+# software over a computer network and provide for limited attribution for the
+# Original Developer. In addition, Exhibit A has been modified to be consistent
+# with Exhibit B.
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
+# the specific language governing rights and limitations under the License.
+#
+# The Original Code is reddit.
+#
+# The Original Developer is the Initial Developer. The Initial Developer of
+# the Original Code is reddit Inc.
+#
+# All portions of the code written by reddit are Copyright (c) 2006-2014 reddit
+# Inc. All Rights Reserved.
+###############################################################################
+
+from pylons import g
+
+from r2.lib import amqp
+from r2.lib.hooks import all_hooks, get_hook
+from r2.models.trylater import TryLater
+
+PREFIX = "trylater."
+
+
+## Entry point
+def run_trylater():
+ our_hooks = (key[len(PREFIX):] for key in all_hooks().keys()
+ if key.startswith(PREFIX))
+ with TryLater.multi_handle(our_hooks) as handleable:
+ for system, mature_items in handleable.iteritems():
+ hook_name = "trylater.%s" % system
+ g.log.info("Trying %s", system)
+
+ get_hook(hook_name).call(mature_items=mature_items)
+
+ amqp.worker.join()
View
12 upstart/reddit-job-trylater.conf
@@ -0,0 +1,12 @@
+description "run events scheduled for later"
+
+manual
+task
+stop on reddit-stop or runlevel [016]
+
+nice 10
+
+script
+ . /etc/default/reddit
+ wrap-job paster run $REDDIT_INI $REDDIT_ROOT/../scripts/trylater.py -c 'run_trylater()'
+end script

0 comments on commit 89762c9

Please sign in to comment.