Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: appengine/cr-buildbucket/service.py

Issue 1082303002: buildbucket: put_batch endpoint (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: removed memcache import Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « appengine/cr-buildbucket/errors.py ('k') | appengine/cr-buildbucket/test/api_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import datetime 5 import datetime
6 import itertools 6 import itertools
7 import json 7 import json
8 import logging 8 import logging
9 import urlparse 9 import urlparse
10 10
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 83
84 84
85 def current_identity_cannot(action_format, *args): 85 def current_identity_cannot(action_format, *args):
86 action = action_format % args 86 action = action_format % args
87 msg = 'User %s cannot %s' % (auth.get_current_identity().to_bytes(), action) 87 msg = 'User %s cannot %s' % (auth.get_current_identity().to_bytes(), action)
88 logging.warning(msg) 88 logging.warning(msg)
89 raise auth.AuthorizationError(msg) 89 raise auth.AuthorizationError(msg)
90 90
91 91
92 class BuildBucketService(object): 92 class BuildBucketService(object):
93 def add( 93 @ndb.tasklet
94 self, bucket, tags=None, parameters=None, lease_expiration_date=None): 94 def add_async(
95 self, bucket, tags=None, parameters=None, lease_expiration_date=None,
96 client_operation_id=None):
95 """Adds the build entity to the build bucket. 97 """Adds the build entity to the build bucket.
96 98
97 Requires the current user to have permissions to add builds to the 99 Requires the current user to have permissions to add builds to the
98 |bucket|. 100 |bucket|.
99 101
100 Args: 102 Args:
101 bucket (str): destination bucket. Required. 103 bucket (str): destination bucket. Required.
102 tags (model.Tags): build tags. 104 tags (model.Tags): build tags.
103 parameters (dict): arbitrary build parameters. Cannot be changed after 105 parameters (dict): arbitrary build parameters. Cannot be changed after
104 build creation. 106 build creation.
105 lease_expiration_date (datetime.datetime): if not None, the build is 107 lease_expiration_date (datetime.datetime): if not None, the build is
106 created as leased and its lease_key is not None. 108 created as leased and its lease_key is not None.
109 client_operation_id (str): client-supplied operation id. If an
110 a build with the same client operation id was added during last minute,
111 it will be returned instead.
107 112
108 Returns: 113 Returns:
109 A new Build. 114 A new Build.
110 """ 115 """
116 if client_operation_id is not None:
117 if not isinstance(client_operation_id, basestring): # pragma: no cover
118 raise errors.InvalidInputError('client_operation_id must be string')
119 if '/' in client_operation_id: # pragma: no cover
120 raise errors.InvalidInputError('client_operation_id must not contain /')
111 validate_bucket_name(bucket) 121 validate_bucket_name(bucket)
112 assert parameters is None or isinstance(parameters, dict) 122 assert parameters is None or isinstance(parameters, dict)
113 validate_lease_expiration_date(lease_expiration_date) 123 validate_lease_expiration_date(lease_expiration_date)
114 validate_tags(tags) 124 validate_tags(tags)
115 tags = tags or [] 125 tags = tags or []
116 126
127 ctx = ndb.get_context()
117 identity = auth.get_current_identity() 128 identity = auth.get_current_identity()
118 if not acl.can_add_build(bucket, identity): 129 if not acl.can_add_build(bucket, identity):
119 raise current_identity_cannot('add builds to bucket %s', bucket) 130 raise current_identity_cannot('add builds to bucket %s', bucket)
120 131
132 if client_operation_id is not None:
133 client_operation_cache_key = (
134 'client_op/%s/%s/add_build' % (
135 identity.to_bytes(), client_operation_id))
136 build_id = yield ctx.memcache_get(client_operation_cache_key)
137 if build_id:
138 build = yield model.Build.get_by_id_async(build_id)
139 if build: # pragma: no branch
140 raise ndb.Return(build)
141
121 build = model.Build( 142 build = model.Build(
122 id=model.new_build_id(), 143 id=model.new_build_id(),
123 bucket=bucket, 144 bucket=bucket,
124 tags=tags, 145 tags=tags,
125 parameters=parameters, 146 parameters=parameters,
126 status=model.BuildStatus.SCHEDULED, 147 status=model.BuildStatus.SCHEDULED,
127 created_by=identity, 148 created_by=identity,
128 ) 149 )
129 if lease_expiration_date is not None: 150 if lease_expiration_date is not None:
130 build.lease_expiration_date = lease_expiration_date 151 build.lease_expiration_date = lease_expiration_date
131 build.leasee = auth.get_current_identity() 152 build.leasee = auth.get_current_identity()
132 build.regenerate_lease_key() 153 build.regenerate_lease_key()
133 build.put() 154 yield build.put_async()
134 logging.info( 155 logging.info(
135 'Build %s was created by %s', build.key.id(), identity.to_bytes()) 156 'Build %s was created by %s', build.key.id(), identity.to_bytes())
136 return build 157
158 if client_operation_id is not None:
159 yield ctx.memcache_set(client_operation_cache_key, build.key.id(), 60)
160 raise ndb.Return(build)
161
162 def add(self, *args, **kwargs):
163 """Sync version of add_async."""
164 return self.add_async(*args, **kwargs).get_result()
137 165
138 def get(self, build_id): 166 def get(self, build_id):
139 """Gets a build by |build_id|. 167 """Gets a build by |build_id|.
140 168
141 Requires the current user to have permissions to view the build. 169 Requires the current user to have permissions to view the build.
142 """ 170 """
143 build = model.Build.get_by_id(build_id) 171 build = model.Build.get_by_id(build_id)
144 if not build: 172 if not build:
145 return None 173 return None
146 identity = auth.get_current_identity() 174 identity = auth.get_current_identity()
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 633
606 def reset_expired_builds(self): 634 def reset_expired_builds(self):
607 """For all building expired builds, resets their lease_key and state.""" 635 """For all building expired builds, resets their lease_key and state."""
608 q = model.Build.query( 636 q = model.Build.query(
609 model.Build.is_leased == True, 637 model.Build.is_leased == True,
610 model.Build.lease_expiration_date <= datetime.datetime.utcnow(), 638 model.Build.lease_expiration_date <= datetime.datetime.utcnow(),
611 ) 639 )
612 for key in q.iter(keys_only=True): 640 for key in q.iter(keys_only=True):
613 if self._reset_expired_build(key): # pragma: no branch 641 if self._reset_expired_build(key): # pragma: no branch
614 logging.info('Expired build %s was reset' % key.id()) 642 logging.info('Expired build %s was reset' % key.id())
OLDNEW
« no previous file with comments | « appengine/cr-buildbucket/errors.py ('k') | appengine/cr-buildbucket/test/api_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698