Trees | Indices | Help |
---|
|
1 """ 2 Methods for working with build Batches. 3 """ 4 5 import anytree 6 7 from coprs import db 8 from coprs.helpers import WorkList 9 from coprs.models import Batch, Build 10 from coprs.exceptions import BadRequest 11 import coprs.logic.builds_logic as bl15 """ Batch logic entrypoint """ 16 @classmethod89 90 @classmethod 102 103 # STILL PENDING 104 # ============= 105 # => some builds are: waiting, pending, starting, running, importing 106 # => the rest is: succeeded/failed 107 # 108 # SUCCEEDED 109 # ========= 110 # => all builds succeeded 111 # 112 # FAILED, BUT FIXABLE 113 # =================== 114 # => all builds are succeeded or failed 115 # => timeout is OK: last ended_on is >= time.time() - deadline 116 # 117 # FAILED 118 # ====== 119 # => some builds failed 120 # => timeout is out 12118 """ 19 Put the build into a new batch, and return the batch. If the build is 20 already assigned to any batch, do nothing and return the batch. 21 22 Locks the build for updates, may block! 23 """ 24 25 # We don't want to create a new batch if one already exists, but there's 26 # the concurrency problem so we need to lock the build instance for 27 # writing. 28 build = db.session.query(Build).with_for_update().get(build_id) 29 if not build: 30 raise BadRequest("Build {} doesn't exist".format(build_id)) 31 32 # Somewhat pedantically, we _should_ lock the batch (if exists) 33 # here because the query for 'build.finished' and 34 # 'build.batch.finished' is a bit racy (backend workers may 35 # asynchronously make the build/batch finished, and we may still 36 # assign some new build to a just finished batch). 37 error = build.batching_user_error(requestor, modify) 38 if error: 39 raise BadRequest(error) 40 41 if build.batch: 42 return build.batch 43 44 batch = Batch() 45 db.session.add(batch) 46 build.batch = batch 47 return batch48 49 @staticmethod51 """ 52 Query for all still not-finished batches, order by id ASC 53 """ 54 batches = set() 55 query = bl.BuildsLogic.processing_builds() 56 for build in query.all(): 57 if build.batch: 58 batches.add(build.batch) 59 return batches60 61 @classmethod63 """ 64 Get all the currently processing batches, together with all the 65 dependency batches which are already finished -- and keep them ordered 66 in list based on theirs ID and dependencies. 67 """ 68 roots = [] 69 node_map = {} 70 def get_mapped_node(batch): 71 if batch.id in node_map: 72 return node_map[batch.id] 73 node_map[batch.id] = anytree.Node(batch) 74 return node_map[batch.id]75 76 # go through all the batches transitively 77 pending_batches = cls.pending_batches() 78 wl = WorkList(pending_batches) 79 while not wl.empty: 80 batch = wl.pop() 81 node = get_mapped_node(batch) 82 if batch.blocked_by_id: 83 parent_node = get_mapped_node(batch.blocked_by) 84 node.parent = parent_node 85 wl.schedule(batch.blocked_by) 86 else: 87 roots.append(node) 88 return roots
Trees | Indices | Help |
---|
Generated by Epydoc 3.0.1 | http://epydoc.sourceforge.net |