def _update_function_db(function_id): with db_api.transaction(): # NOTE(kong): Store function info in cache? func_db = db_api.get_function(function_id) runtime_db = func_db.runtime if runtime_db and runtime_db.status != status.AVAILABLE: raise exc.RuntimeNotAvailableException( 'Runtime %s is not available.' % func_db.runtime_id) # Function update is done using UPDATE ... FROM ... WHERE # non-locking clause. while func_db: count = func_db.count modified = db_api.conditional_update( models.Function, { 'count': count + 1, }, { 'id': function_id, 'count': count }, insecure=True, ) if not modified: LOG.warning("Retrying to update function count.") func_db = db_api.get_function(function_id) continue else: break return func_db.runtime_id
def _update_function_version_db(version_id, pre_count): # Update is done using UPDATE ... FROM ... WHERE non-locking clause. while True: modified = db_api.conditional_update( models.FunctionVersion, { 'count': pre_count + 1, }, { 'id': version_id, 'count': pre_count }, insecure=True, ) if not modified: LOG.warning("Retrying to update function version count.") pre_count += 1 continue else: break
def handle_job(engine_client): """Execute job task with no db transactions.""" for job in db_api.get_next_jobs(timeutils.utcnow() + timedelta(seconds=3)): job_id = job.id func_id = job.function_id LOG.debug("Processing job: %s, function: %s", job_id, func_id) func_db = db_api.get_function(func_id, insecure=True) trust_id = func_db.trust_id try: # Setup context before schedule job. ctx = keystone_utils.create_trust_context(trust_id, job.project_id) context.set_ctx(ctx) if (job.count is not None and job.count > 0): job.count -= 1 # Job delete/update is done using UPDATE ... FROM ... WHERE # non-locking clause. if job.count == 0: modified = db_api.conditional_update( models.Job, { 'status': status.DONE, 'count': 0 }, { 'id': job_id, 'status': status.RUNNING }, insecure=True, ) else: next_time = jobs.get_next_execution_time( job.pattern, job.next_execution_time) modified = db_api.conditional_update( models.Job, { 'next_execution_time': next_time, 'count': job.count }, { 'id': job_id, 'next_execution_time': job.next_execution_time }, insecure=True, ) if not modified: LOG.warning( 'Job %s has been already handled by another periodic ' 'task.', job_id) continue LOG.debug("Starting to execute function %s by job %s", func_id, job_id) params = { 'function_id': func_id, 'input': job.function_input, 'sync': False, 'description': constants.EXECUTION_BY_JOB % job_id } executions.create_execution(engine_client, params) except Exception: LOG.exception("Failed to process job %s", job_id) finally: context.set_ctx(None)