diff options
author | Jenkins <jenkins@review.openstack.org> | 2015-06-29 02:55:01 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2015-06-29 02:55:01 +0000 |
commit | a948f43aac6e95e5e5269ce85e2ebb42b3cd1933 (patch) | |
tree | 2cf711678e0c13dcf2f3d82ff6983a6c967514e5 /taskflow/examples | |
parent | 1d41818444b5cb7f37b73be370a81faab6606c64 (diff) | |
parent | 4f867db055eb74890dd1f46d104ea161a6bc84de (diff) | |
download | taskflow-a948f43aac6e95e5e5269ce85e2ebb42b3cd1933.tar.gz |
Merge "Add indestructible 99 bottles of beer example"
Diffstat (limited to 'taskflow/examples')
-rw-r--r-- | taskflow/examples/99_bottles.py | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/taskflow/examples/99_bottles.py b/taskflow/examples/99_bottles.py new file mode 100644 index 0000000..9959255 --- /dev/null +++ b/taskflow/examples/99_bottles.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2015 Yahoo! Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import contextlib +import logging +import os +import sys +import time + +logging.basicConfig(level=logging.ERROR) + +top_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), + os.pardir, + os.pardir)) +sys.path.insert(0, top_dir) + +from taskflow.conductors import backends as conductor_backends +from taskflow import engines +from taskflow.jobs import backends as job_backends +from taskflow.patterns import linear_flow as lf +from taskflow.persistence import backends as persistence_backends +from taskflow.persistence import logbook +from taskflow import task + +from oslo_utils import uuidutils + +# Instructions! +# +# 1. Install zookeeper (or change host listed below) +# 2. Download this example, place in file '99_bottles.py' +# 3. Run `python 99_bottles.py p` to place a song request onto the jobboard +# 4. Run `python 99_bottles.py c` a few times (in different shells) +# 5. On demand kill previously listed processes created in (4) and watch +# the work resume on another process (and repeat) +# 6. Keep enough workers alive to eventually finish the song (if desired). + +ME = os.getpid() +ZK_HOST = "localhost:2181" +JB_CONF = { + 'hosts': ZK_HOST, + 'board': 'zookeeper', + 'path': '/taskflow/99-bottles-demo', +} +DB_URI = r"sqlite:////tmp/bottles.db" +PART_DELAY = 1.0 +HOW_MANY_BOTTLES = 99 + + +class TakeABottleDownPassItAround(task.Task): + def execute(self, bottles_left): + sys.stdout.write('Take one down, ') + time.sleep(PART_DELAY) + sys.stdout.write('pass it around, ') + time.sleep(PART_DELAY) + sys.stdout.write('%s bottles of beer on the wall...\n' % bottles_left) + + +def make_bottles(count): + s = lf.Flow("bottle-song") + for bottle in reversed(list(range(1, count + 1))): + t = TakeABottleDownPassItAround("take-bottle-%s" % bottle, + inject={"bottles_left": bottle - 1}) + s.add(t) + return s + + +def run_conductor(): + print("Starting conductor with pid: %s" % ME) + my_name = "conductor-%s" % ME + persist_backend = persistence_backends.fetch(DB_URI) + with contextlib.closing(persist_backend): + with contextlib.closing(persist_backend.get_connection()) as conn: + conn.upgrade() + job_backend = job_backends.fetch(my_name, JB_CONF, + persistence=persist_backend) + job_backend.connect() + with contextlib.closing(job_backend): + cond = conductor_backends.fetch('blocking', my_name, job_backend, + persistence=persist_backend) + # Run forever, and kill -9 me... + # + # TODO(harlowja): it would be nicer if we could handle + # ctrl-c better... + cond.run() + + +def run_poster(): + print("Starting poster with pid: %s" % ME) + my_name = "poster-%s" % ME + persist_backend = persistence_backends.fetch(DB_URI) + with contextlib.closing(persist_backend): + with contextlib.closing(persist_backend.get_connection()) as conn: + conn.upgrade() + job_backend = job_backends.fetch(my_name, JB_CONF, + persistence=persist_backend) + job_backend.connect() + with contextlib.closing(job_backend): + # Create information in the persistence backend about the + # unit of work we want to complete and the factory that + # can be called to create the tasks that the work unit needs + # to be done. + lb = logbook.LogBook("post-from-%s" % my_name) + fd = logbook.FlowDetail("song-from-%s" % my_name, + uuidutils.generate_uuid()) + lb.add(fd) + with contextlib.closing(persist_backend.get_connection()) as conn: + conn.save_logbook(lb) + engines.save_factory_details(fd, make_bottles, + [HOW_MANY_BOTTLES], {}, + backend=persist_backend) + # Post, and be done with it! + job_backend.post("song-from-%s" % my_name, book=lb) + + +def main(): + if len(sys.argv) == 1: + sys.stderr.write("%s p|c\n" % os.path.basename(sys.argv[0])) + return + if sys.argv[1] == 'p': + run_poster() + if sys.argv[1] == 'c': + run_conductor() + + +if __name__ == '__main__': + main() |