Python google.appengine.ext.ndb.transactional() Examples

The following are 30 code examples of google.appengine.ext.ndb.transactional(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module google.appengine.ext.ndb , or try the search function .
Example #1
Source File: models.py    From sndlatr with Apache License 2.0 6 votes vote down vote up
def add_to_queue(self, url=None, target_state='queued', countdown=0):
        """
        Adds job to task queue and transactionally updates state to 'queued'
        and saves job.
        Does nothing if state is not 'scheduled'.
        """
        if self.state != 'scheduled':
            logging.warn('tried to add job {} with state {}, to queue, '
                         'doing nothing'.format(self.key, self.state))
            return
        if url is None:
            url = self.queue_url
        logging.debug(u'scheduling job {} for {}'.format(self.key,
                                                        self.user_email))
        taskqueue.add(url=url,
                      payload=json.dumps({'key': self.key.urlsafe()}),
                      queue_name=self.queue_name,
                      countdown=countdown,
                      transactional=True)
        self.state = target_state
        self.put() 
Example #2
Source File: api.py    From upvote with Apache License 2.0 6 votes vote down vote up
def Revoke(exm_key, details):
  """Transitions an Exemption to the REVOKED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: List of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Revoking Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.REVOKED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.REVOKED))

  _EnableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.REVOKED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.REVOKED, details=details, transactional=True) 
Example #3
Source File: api.py    From upvote with Apache License 2.0 6 votes vote down vote up
def Expire(exm_key):
  """Transitions an Exemption to the EXPIRED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Expiring Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.EXPIRED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.EXPIRED))

  _EnableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(exm_key, _STATE.EXPIRED)
  notify.DeferUpdateEmail(exm_key, _STATE.EXPIRED, transactional=True) 
Example #4
Source File: api.py    From upvote with Apache License 2.0 6 votes vote down vote up
def Deny(exm_key, details=None):
  """Transitions an Exemption to the DENIED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: Optional list of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Denying Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.DENIED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.DENIED))

  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.DENIED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.DENIED, details=details, transactional=True) 
Example #5
Source File: api.py    From upvote with Apache License 2.0 6 votes vote down vote up
def Approve(exm_key, details=None):
  """Transitions an Exemption to the APPROVED state.

  Args:
    exm_key: The NDB Key of the Exemption entity.
    details: Optional list of strings describing the rationale.

  Raises:
    InvalidStateChangeError: If the desired state cannot be transitioned to from
        the current state.
  """
  host_id = exemption_models.Exemption.GetHostId(exm_key)
  logging.info('Approving Exemption for Host %s', host_id)

  # Verify that the desired state change is still valid.
  exm = exm_key.get()
  if not exm.CanChangeToState(_STATE.APPROVED):
    raise InvalidStateChangeError('%s to %s' % (exm.state, _STATE.APPROVED))

  _DisableLockdown(exm_key)
  exemption_models.Exemption.ChangeState(
      exm_key, _STATE.APPROVED, details=details)
  notify.DeferUpdateEmail(
      exm_key, _STATE.APPROVED, details=details, transactional=True) 
Example #6
Source File: tables_test.py    From upvote with Apache License 2.0 6 votes vote down vote up
def testDoInsertRow_Repeats_InsideTransaction(self, mock_get):

    attempts = 3
    mock_get.side_effect = [None] + [True] * (attempts - 1)

    @ndb.transactional
    def _RepeatedInserts():
      for _ in xrange(attempts):
        now = datetime.datetime.utcnow()
        row_values = {'aaa': True, 'bbb': 4, 'timestamp': now}
        TEST_TABLE._DoInsertRow(**row_values)

    _RepeatedInserts()

    self.assertEqual(1, self.mock_send_to_bigquery.call_count)
    self.assertTrue(tables.monitoring.row_insertions.Success.called)
    self.mock_send_to_bigquery.reset_mock() 
Example #7
Source File: model.py    From cloud-playground with Apache License 2.0 6 votes vote down vote up
def AdoptProjects(dst_user_id, src_user_id):
  """Transfer project ownership to a new user."""

  @ndb.transactional(xg=True)
  def _AdoptProject(project_key, dst_user_key, src_user_key):
    prj, dst_user, src_user = ndb.get_multi([project_key, dst_user_key,
                                             src_user_key])
    if project_key not in src_user.projects:
      # another concurrent request and transaction beat us to it
      return
    src_user.projects.remove(project_key)
    dst_user.projects.append(project_key)
    prj.owner = dst_user_key.id()
    prj.writers.remove(src_user_key.id())
    prj.writers.append(dst_user_key.id())
    ndb.put_multi([prj, dst_user, src_user])

  src_user = GetUser(src_user_id)
  if not src_user or not src_user.projects:
    return
  dst_user = GetOrCreateUser(dst_user_id)
  for project_key in src_user.projects:
    # slow, but transactionable
    _AdoptProject(project_key, dst_user.key, src_user.key) 
Example #8
Source File: change_log.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def enqueue_process_change_task(auth_db_rev):
  """Transactionally adds a call to 'process_change' to the task queue.

  Pins the task to currently executing version of BACKEND_MODULE module
  (defined in config.py).

  Added as AuthDB commit callback in get_backend_routes() below.
  """
  assert ndb.in_transaction()
  conf = config.ensure_configured()
  try:
    # Pin the task to the module and version.
    taskqueue.add(
        url='/internal/auth/taskqueue/process-change/%d' % auth_db_rev,
        queue_name=conf.PROCESS_CHANGE_TASK_QUEUE,
        headers={'Host': modules.get_hostname(module=conf.BACKEND_MODULE)},
        transactional=True)
  except Exception as e:
    logging.error(
        'Problem adding "process-change" task to the task queue (%s): %s',
        e.__class__.__name__, e)
    raise 
Example #9
Source File: gcs.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def authorize_reader(email):
  """Allows the given user to fetch AuthDB Google Storage file.

  Raises:
    Error if reached GCS ACL entries limit or GCS call fails.
  """
  @ndb.transactional
  def add_if_necessary():
    readers = _list_authorized_readers()
    if email in readers:
      return
    if len(readers) >= _MAX_ACL_ENTRIES:
      raise Error('Reached the soft limit on GCS ACL entries')
    reader = AuthDBReader(
        key=_auth_db_reader_key(email),
        authorized_at=utils.utcnow())
    reader.put()

  add_if_necessary()
  _update_gcs_acls() 
Example #10
Source File: change_log.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def enqueue_process_change_task(auth_db_rev):
  """Transactionally adds a call to 'process_change' to the task queue.

  Pins the task to currently executing version of BACKEND_MODULE module
  (defined in config.py).

  Added as AuthDB commit callback in get_backend_routes() below.
  """
  assert ndb.in_transaction()
  conf = config.ensure_configured()
  try:
    # Pin the task to the module and version.
    taskqueue.add(
        url='/internal/auth/taskqueue/process-change/%d' % auth_db_rev,
        queue_name=conf.PROCESS_CHANGE_TASK_QUEUE,
        headers={'Host': modules.get_hostname(module=conf.BACKEND_MODULE)},
        transactional=True)
  except Exception as e:
    logging.error(
        'Problem adding "process-change" task to the task queue (%s): %s',
        e.__class__.__name__, e)
    raise 
Example #11
Source File: change_log.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def enqueue_process_change_task(auth_db_rev):
  """Transactionally adds a call to 'process_change' to the task queue.

  Pins the task to currently executing version of BACKEND_MODULE module
  (defined in config.py).

  Added as AuthDB commit callback in get_backend_routes() below.
  """
  assert ndb.in_transaction()
  conf = config.ensure_configured()
  try:
    # Pin the task to the module and version.
    taskqueue.add(
        url='/internal/auth/taskqueue/process-change/%d' % auth_db_rev,
        queue_name=conf.PROCESS_CHANGE_TASK_QUEUE,
        headers={'Host': modules.get_hostname(module=conf.BACKEND_MODULE)},
        transactional=True)
  except Exception as e:
    logging.error(
        'Problem adding "process-change" task to the task queue (%s): %s',
        e.__class__.__name__, e)
    raise 
Example #12
Source File: change_log.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def enqueue_process_change_task(auth_db_rev):
  """Transactionally adds a call to 'process_change' to the task queue.

  Pins the task to currently executing version of BACKEND_MODULE module
  (defined in config.py).

  Added as AuthDB commit callback in get_backend_routes() below.
  """
  assert ndb.in_transaction()
  conf = config.ensure_configured()
  try:
    # Pin the task to the module and version.
    taskqueue.add(
        url='/internal/auth/taskqueue/process-change/%d' % auth_db_rev,
        queue_name=conf.PROCESS_CHANGE_TASK_QUEUE,
        headers={'Host': modules.get_hostname(module=conf.BACKEND_MODULE)},
        transactional=True)
  except Exception as e:
    logging.error(
        'Problem adding "process-change" task to the task queue (%s): %s',
        e.__class__.__name__, e)
    raise 
Example #13
Source File: change_log.py    From luci-py with Apache License 2.0 6 votes vote down vote up
def enqueue_process_change_task(auth_db_rev):
  """Transactionally adds a call to 'process_change' to the task queue.

  Pins the task to currently executing version of BACKEND_MODULE module
  (defined in config.py).

  Added as AuthDB commit callback in get_backend_routes() below.
  """
  assert ndb.in_transaction()
  conf = config.ensure_configured()
  try:
    # Pin the task to the module and version.
    taskqueue.add(
        url='/internal/auth/taskqueue/process-change/%d' % auth_db_rev,
        queue_name=conf.PROCESS_CHANGE_TASK_QUEUE,
        headers={'Host': modules.get_hostname(module=conf.BACKEND_MODULE)},
        transactional=True)
  except Exception as e:
    logging.error(
        'Problem adding "process-change" task to the task queue (%s): %s',
        e.__class__.__name__, e)
    raise 
Example #14
Source File: main.py    From python-docs-samples with Apache License 2.0 6 votes vote down vote up
def add_note():
    page_name = flask.request.args.get('page_name', 'default')
    note_title = flask.request.form['note_title']
    note_text = flask.request.form['note_text']

    parent = parent_key(page_name)

    choice = random.randint(0, 1)
    if choice == 0:
        # Use transactional function
        # [START calling]
        note_key = ndb.Key(Note, note_title, parent=parent)
        note = Note(key=note_key, content=note_text)
        # [END calling]
        if pick_random_insert(note_key, note) is False:
            return ('Already there<br><a href="%s">Return</a>'
                    % flask.url_for('main_page', page_name=page_name))
        return flask.redirect(flask.url_for('main_page', page_name=page_name))
    elif choice == 1:
        # Use get_or_insert, which is transactional
        note = Note.get_or_insert(note_title, parent=parent, content=note_text)
        if note.content != note_text:
            return ('Already there<br><a href="%s">Return</a>'
                    % flask.url_for('main_page', page_name=page_name))
        return flask.redirect(flask.url_for('main_page', page_name=page_name)) 
Example #15
Source File: gitiles_import.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def import_project(project_id):
  if not config.validation.is_valid_project_id(project_id):
    raise ValueError('Invalid project id: %s' % project_id)

  config_set = 'projects/%s' % project_id

  project = projects.get_project(project_id)
  if project is None:
    raise NotFoundError('project %s not found' % project_id)
  if project.config_location.storage_type != GITILES_LOCATION_TYPE:
    raise Error('project %s is not a Gitiles project' % project_id)

  try:
    loc = _resolved_location(project.config_location.url)
  except gitiles.TreeishResolutionError:
    logging.warning('could not resolve URL %r', project.config_location.url)

    @ndb.transactional
    def txn():
      key = ndb.Key(storage.ConfigSet, config_set)
      if key.get():
        logging.warning('deleting project %s with unresolved URL', project_id)
        key.delete()

    txn()
    return

  # Update project repo info.
  repo_url = str(loc._replace(treeish=None, path=None))
  projects.update_import_info(
      project_id, projects.RepositoryType.GITILES, repo_url)

  _import_config_set(config_set, loc, project_id) 
Example #16
Source File: change_log_test.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def test_works(self):
    # Initial entities. Don't call 'record_revision' to imitate "old"
    # application without history related code.
    @ndb.transactional
    def make_auth_db():
      model.AuthGlobalConfig(key=model.root_key()).put()
      model.AuthIPWhitelistAssignments(
          key=model.ip_whitelist_assignments_key()).put()
      model.AuthGroup(key=model.group_key('A group')).put()
      model.AuthIPWhitelist(key=model.ip_whitelist_key('A whitelist')).put()
      model.replicate_auth_db()
    make_auth_db()

    # Bump auth_db once more to avoid hitting trivial case of "processing first
    # revision ever".
    auth_db_rev = ndb.transaction(model.replicate_auth_db)
    self.assertEqual(2, auth_db_rev)

    # Now do the work.
    change_log.ensure_initial_snapshot(auth_db_rev)

    # Generated new AuthDB rev with updated entities.
    self.assertEqual(3, model.get_auth_db_revision())

    # Check all *History entities exist now.
    p = model.historical_revision_key(3)
    self.assertIsNotNone(
        ndb.Key('AuthGlobalConfigHistory', 'root', parent=p).get())
    self.assertIsNotNone(
        ndb.Key(
            'AuthIPWhitelistAssignmentsHistory', 'default', parent=p).get())
    self.assertIsNotNone(ndb.Key('AuthGroupHistory', 'A group', parent=p).get())
    self.assertIsNotNone(
        ndb.Key('AuthIPWhitelistHistory', 'A whitelist', parent=p).get())

    # Call again, should be noop (marker is set).
    change_log.ensure_initial_snapshot(3)
    self.assertEqual(3, model.get_auth_db_revision()) 
Example #17
Source File: model.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def bootstrap(cls, name, length=32):
    """Creates a secret if it doesn't exist yet.

    Args:
      name: name of the secret.
      length: length of the secret to generate if secret doesn't exist yet.

    Returns:
      Instance of AuthSecret (creating it if necessary) with random secret set.
    """
    # Note that 'get_or_insert' is a bad fit here. With 'get_or_insert' we'd
    # have to call os.urandom every time we want to get a key. It's a waste of
    # time and entropy.
    key = ndb.Key(
        cls, name,
        parent=ndb.Key(AuthSecretScope, 'local', parent=root_key()))
    entity = key.get()
    if entity is not None:
      return entity
    @ndb.transactional
    def create():
      entity = key.get()
      if entity is not None:
        return entity
      logging.info('Creating new secret key %s', name)
      entity = cls(
          key=key,
          values=[os.urandom(length)],
          modified_by=get_service_self_identity())
      entity.put()
      return entity
    return create()


################################################################################
## IP whitelist. 
Example #18
Source File: rest_api.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def post(self):
    if is_config_locked():
      self.abort_with_error(409, text='The configuration is managed elsewhere')

    body = self.parse_body()
    try:
      client_id = body['client_id']
      client_secret = body['client_not_so_secret']
      additional_client_ids = filter(bool, body['additional_client_ids'])
      token_server_url = body['token_server_url']
    except KeyError as exc:
      self.abort_with_error(400, text='Missing key %s' % exc)

    if token_server_url:
      try:
        utils.validate_root_service_url(token_server_url)
      except ValueError as exc:
        self.abort_with_error(400, text='Invalid token server URL - %s' % exc)

    @ndb.transactional
    def update():
      config = model.root_key().get()
      config.populate(
          oauth_client_id=client_id,
          oauth_client_secret=client_secret,
          oauth_additional_client_ids=additional_client_ids,
          token_server_url=token_server_url)
      config.record_revision(
          modified_by=api.get_current_identity(),
          modified_ts=utils.utcnow(),
          comment='REST API')
      config.put()
      model.replicate_auth_db()

    update()
    self.send_response({'ok': True}) 
Example #19
Source File: change_log_test.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def test_works(self):
    # Initial entities. Don't call 'record_revision' to imitate "old"
    # application without history related code.
    @ndb.transactional
    def make_auth_db():
      model.AuthGlobalConfig(key=model.root_key()).put()
      model.AuthIPWhitelistAssignments(
          key=model.ip_whitelist_assignments_key()).put()
      model.AuthGroup(key=model.group_key('A group')).put()
      model.AuthIPWhitelist(key=model.ip_whitelist_key('A whitelist')).put()
      model.replicate_auth_db()
    make_auth_db()

    # Bump auth_db once more to avoid hitting trivial case of "processing first
    # revision ever".
    auth_db_rev = ndb.transaction(model.replicate_auth_db)
    self.assertEqual(2, auth_db_rev)

    # Now do the work.
    change_log.ensure_initial_snapshot(auth_db_rev)

    # Generated new AuthDB rev with updated entities.
    self.assertEqual(3, model.get_auth_db_revision())

    # Check all *History entities exist now.
    p = model.historical_revision_key(3)
    self.assertIsNotNone(
        ndb.Key('AuthGlobalConfigHistory', 'root', parent=p).get())
    self.assertIsNotNone(
        ndb.Key(
            'AuthIPWhitelistAssignmentsHistory', 'default', parent=p).get())
    self.assertIsNotNone(ndb.Key('AuthGroupHistory', 'A group', parent=p).get())
    self.assertIsNotNone(
        ndb.Key('AuthIPWhitelistHistory', 'A whitelist', parent=p).get())

    # Call again, should be noop (marker is set).
    change_log.ensure_initial_snapshot(3)
    self.assertEqual(3, model.get_auth_db_revision()) 
Example #20
Source File: config.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def check_permission_changes(db):
  """Returns jobs to update permissions list stored in the AuthDB.

  The AuthDB distributed to all services contains a list of all defined
  permissions. This list is a superset of permissions referenced by all realms.
  In particular, it may have entries that are not yet used in any realm.
  Downstream services are still interested in seeing them (for example, to
  compare with the list of permissions the service is interested in checking,
  to catch typos and misconfigurations).

  Args:
    db: a permissions.DB instance with current permissions and roles.

  Returns:
    A list of parameterless callbacks.
  """
  perms_to_map = lambda perms: {p.name: p for p in perms}

  stored = model.realms_globals_key().get()
  if stored and perms_to_map(stored.permissions) == db.permissions:
    return []  # permissions in the AuthDB are up to date

  logging.info('Updating permissions in AuthDB to rev "%s"', db.revision)

  @ndb.transactional
  def update_stored():
    stored = model.realms_globals_key().get()
    if not stored:
      stored = model.AuthRealmsGlobals(key=model.realms_globals_key())
    if perms_to_map(stored.permissions) == db.permissions:
      logging.info('Skipping, already up-to-date')
      return
    stored.permissions = sorted(db.permissions.values(), key=lambda p: p.name)
    stored.record_revision(
        modified_by=model.get_service_self_identity(),
        comment='Updating permissions to rev "%s"' % db.revision)
    stored.put()
    model.replicate_auth_db()

  return [update_stored] 
Example #21
Source File: model.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def bootstrap(cls, name, length=32):
    """Creates a secret if it doesn't exist yet.

    Args:
      name: name of the secret.
      length: length of the secret to generate if secret doesn't exist yet.

    Returns:
      Instance of AuthSecret (creating it if necessary) with random secret set.
    """
    # Note that 'get_or_insert' is a bad fit here. With 'get_or_insert' we'd
    # have to call os.urandom every time we want to get a key. It's a waste of
    # time and entropy.
    key = ndb.Key(
        cls, name,
        parent=ndb.Key(AuthSecretScope, 'local', parent=root_key()))
    entity = key.get()
    if entity is not None:
      return entity
    @ndb.transactional
    def create():
      entity = key.get()
      if entity is not None:
        return entity
      logging.info('Creating new secret key %s', name)
      entity = cls(
          key=key,
          values=[os.urandom(length)],
          modified_by=get_service_self_identity())
      entity.put()
      return entity
    return create()


################################################################################
## IP whitelist. 
Example #22
Source File: rest_api.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def post(self):
    if is_config_locked():
      self.abort_with_error(409, text='The configuration is managed elsewhere')

    body = self.parse_body()
    try:
      client_id = body['client_id']
      client_secret = body['client_not_so_secret']
      additional_client_ids = filter(bool, body['additional_client_ids'])
      token_server_url = body['token_server_url']
    except KeyError as exc:
      self.abort_with_error(400, text='Missing key %s' % exc)

    if token_server_url:
      try:
        utils.validate_root_service_url(token_server_url)
      except ValueError as exc:
        self.abort_with_error(400, text='Invalid token server URL - %s' % exc)

    @ndb.transactional
    def update():
      config = model.root_key().get()
      config.populate(
          oauth_client_id=client_id,
          oauth_client_secret=client_secret,
          oauth_additional_client_ids=additional_client_ids,
          token_server_url=token_server_url)
      config.record_revision(
          modified_by=api.get_current_identity(),
          modified_ts=utils.utcnow(),
          comment='REST API')
      config.put()
      model.replicate_auth_db()

    update()
    self.send_response({'ok': True}) 
Example #23
Source File: model.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def bootstrap(cls, name, length=32):
    """Creates a secret if it doesn't exist yet.

    Args:
      name: name of the secret.
      length: length of the secret to generate if secret doesn't exist yet.

    Returns:
      Instance of AuthSecret (creating it if necessary) with random secret set.
    """
    # Note that 'get_or_insert' is a bad fit here. With 'get_or_insert' we'd
    # have to call os.urandom every time we want to get a key. It's a waste of
    # time and entropy.
    key = ndb.Key(
        cls, name,
        parent=ndb.Key(AuthSecretScope, 'local', parent=root_key()))
    entity = key.get()
    if entity is not None:
      return entity
    @ndb.transactional
    def create():
      entity = key.get()
      if entity is not None:
        return entity
      logging.info('Creating new secret key %s', name)
      entity = cls(
          key=key,
          values=[os.urandom(length)],
          modified_by=get_service_self_identity())
      entity.put()
      return entity
    return create()


################################################################################
## IP whitelist. 
Example #24
Source File: change_log_test.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def test_works(self):
    # Initial entities. Don't call 'record_revision' to imitate "old"
    # application without history related code.
    @ndb.transactional
    def make_auth_db():
      model.AuthGlobalConfig(key=model.root_key()).put()
      model.AuthIPWhitelistAssignments(
          key=model.ip_whitelist_assignments_key()).put()
      model.AuthGroup(key=model.group_key('A group')).put()
      model.AuthIPWhitelist(key=model.ip_whitelist_key('A whitelist')).put()
      model.replicate_auth_db()
    make_auth_db()

    # Bump auth_db once more to avoid hitting trivial case of "processing first
    # revision ever".
    auth_db_rev = ndb.transaction(model.replicate_auth_db)
    self.assertEqual(2, auth_db_rev)

    # Now do the work.
    change_log.ensure_initial_snapshot(auth_db_rev)

    # Generated new AuthDB rev with updated entities.
    self.assertEqual(3, model.get_auth_db_revision())

    # Check all *History entities exist now.
    p = model.historical_revision_key(3)
    self.assertIsNotNone(
        ndb.Key('AuthGlobalConfigHistory', 'root', parent=p).get())
    self.assertIsNotNone(
        ndb.Key(
            'AuthIPWhitelistAssignmentsHistory', 'default', parent=p).get())
    self.assertIsNotNone(ndb.Key('AuthGroupHistory', 'A group', parent=p).get())
    self.assertIsNotNone(
        ndb.Key('AuthIPWhitelistHistory', 'A whitelist', parent=p).get())

    # Call again, should be noop (marker is set).
    change_log.ensure_initial_snapshot(3)
    self.assertEqual(3, model.get_auth_db_revision()) 
Example #25
Source File: model.py    From cloud-playground with Apache License 2.0 5 votes vote down vote up
def DeleteProject(project):
  """Delete an existing project."""
  assert project
  tree = _CreateProjectTree(project)
  # 1. delete files
  tree.Clear()

  @ndb.transactional(xg=True)
  def DelProject():
    # 2. get current entities
    prj = project.key.get()
    user_key = ndb.Key(User, prj.owner, namespace=settings.PLAYGROUND_NAMESPACE)
    usr = user_key.get()
    # 3. delete project
    prj.key.delete()
    # 4. delete project references
    if prj.key in usr.projects:
      usr.projects.remove(prj.key)
      usr.put()
    else:
      shared.i('ignoring project key {} not found in user projects {}'
               .format(prj.key, usr.projects))

  @ndb.transactional(xg=True)
  def DelReposAndProject(keys):
    ndb.delete_multi(keys)
    DelProject()

  repo_query = Repo.query(namespace=settings.PLAYGROUND_NAMESPACE)
  repo_query = repo_query.filter(Repo.project == project.key)
  keys = repo_query.fetch(keys_only=True)
  if keys:
    DelReposAndProject(keys)
  else:
    DelProject() 
Example #26
Source File: templates.py    From cloud-playground with Apache License 2.0 5 votes vote down vote up
def _GetRepoCollections():
  repo_collections = []
  for uri, description in REPO_COLLECTIONS:
    repo_collection = model.GetOrInsertRepoCollection(uri, description)
    task = taskqueue.add(queue_name='repo',
                         url='/_playground_tasks/populate_repo_collection',
                         params={
                             'repo_collection_url': repo_collection.key.id(),
                         }, transactional=True)
    shared.w('adding task {} to populate repo collection {!r}'.format(task.name,
                                                                      uri))
    repo_collections.append(repo_collection)
  ndb.put_multi(repo_collections)
  return repo_collections 
Example #27
Source File: handlers_endpoints_v1.py    From luci-py with Apache License 2.0 5 votes vote down vote up
def store_and_enqueue_verify_task(entry, task_queue_host):
  entry.put()
  taskqueue.add(
      url='/internal/taskqueue/verify/%s' % entry.key.id(),
      params={'req': os.environ['REQUEST_LOG_ID']},
      queue_name='verify',
      headers={'Host': task_queue_host},
      transactional=True,
  ) 
Example #28
Source File: main.py    From python-docs-samples with Apache License 2.0 5 votes vote down vote up
def insert_if_absent_taskq(note_key, note):
    taskqueue.add(url=flask.url_for('taskq_worker'), transactional=True)
    # do insert
    # [END taskq]
    fetch = note_key.get()
    if fetch is None:
        note.put()
        return True
    return False 
Example #29
Source File: worker.py    From python-docs-samples with Apache License 2.0 5 votes vote down vote up
def post(self):
        amount = int(self.request.get('amount'))

        # This task should run at most once per second because of the datastore
        # transaction write throughput.
        @ndb.transactional
        def update_counter():
            counter = Counter.get_or_insert(COUNTER_KEY, count=0)
            counter.count += amount
            counter.put()

        update_counter() 
Example #30
Source File: stream_to_bigquery.py    From loaner with Apache License 2.0 5 votes vote down vote up
def stream_rows_wrapper(self):
    """Streams rows ensuring that it is transactional."""
    deferred.defer(
        bigquery_row_model.BigQueryRow.stream_rows, _transactional=True)