コード例 #1
0
    def _ValidateRemoveOneContact(contact_id):
        predicate = lambda c: c.contact_id == contact_id
        existing_contacts = validator.QueryModelObjects(Contact,
                                                        predicate=predicate,
                                                        query_forward=True)
        if len(existing_contacts) > 0:
            last_contact = existing_contacts[-1]
            if last_contact.IsRemoved():
                # Keep the last matching contact because it's already been removed.
                existing_contacts = existing_contacts[:-1]
            elif not removed_contacts_reset:
                removed_contact_dict = {
                    'user_id':
                    user_id,
                    'contact_id':
                    contact_id,
                    'contact_source':
                    Contact.GetContactSourceFromContactId(contact_id),
                    'timestamp':
                    util._TEST_TIME,
                    'sort_key':
                    Contact.CreateSortKey(contact_id, util._TEST_TIME),
                    'labels': [Contact.REMOVED]
                }
                validator.ValidateCreateContact(identities_properties=None,
                                                **removed_contact_dict)

            for contact in existing_contacts:
                db_key = DBKey(user_id, contact.sort_key)
                validator.ValidateDeleteDBObject(Contact, db_key)
コード例 #2
0
    def _Check(self):
        """Check and prepare for remove.
    Along with checks, builds two lists for the Update phase.
    1) self._contacts_to_delete: list of contacts which have been superseded by more recent
        contacts with the same contact_id and because they no longer serve any purpose should
        be deleted.  These may exist due to lack of transactional atomicity when replacing
        a contact as part of removal or upload.  If too many removed contacts are or will exist, this
        list will also contain all of the removed contacts as well as any contacts that are
        part of the removal request.
    2) self._contacts_to_remove: list of contacts which should be transitioned to 'removed', but
        currently are not in the 'removed' state.
    """
        # Check for well formed input and build dict of all contacts that have been requested for removal.
        for request_contact_id in self._request_contact_ids:
            if Contact.GetContactSourceFromContactId(
                    request_contact_id) not in Contact.UPLOAD_SOURCES:
                # remove_contacts only allows removal of Manual and iPhone sourced contacts.
                raise InvalidRequestError(
                    BAD_CONTACT_SOURCE,
                    Contact.GetContactSourceFromContactId(request_contact_id))

        # Get existing contacts along with list of contacts that should be deleted as part of dedup.
        existing_contacts_dict, self._contacts_to_delete = \
            yield RemoveContactsOperation._GetAllContactsWithDedup(self._client, self._user_id)

        # Projected count of removed contacts after this operation.
        removed_contact_count = 0
        # Build list of contacts to be removed.
        for existing_contact in existing_contacts_dict.itervalues():
            if existing_contact.IsRemoved():
                removed_contact_count += 1
            elif existing_contact.contact_id in self._request_contact_ids:
                # Not already in removed state, so add to list of contacts to remove during update stage.
                self._contacts_to_remove.append(existing_contact)
                removed_contact_count += 1
            # else case is no-op because there's no match of existing present contact and one being requested for removal.

        if removed_contact_count >= Contact.MAX_REMOVED_CONTACTS_LIMIT:
            # Trigger removed contact reset (garbage collection).
            self._removed_contacts_reset = True

        if self._op.checkpoint is None:
            # Set checkpoint.
            # Checkpoint whether or not we decided to reset the removed contacts.
            yield self._op.SetCheckpoint(
                self._client,
                {'removed_contacts_reset': self._removed_contacts_reset})
        elif not self._removed_contacts_reset:
            # Even if we didn't decide during this operation retry to reset the removed contacts, we still need to do it
            #   if we previously decided to because we may have already deleted some of the removed contacts and need to
            #   indicate the removed contact reset in the notification.
            self._removed_contacts_reset = self._op.checkpoint[
                'removed_contacts_reset']

        if self._removed_contacts_reset:
            # Because we've decided to reset the contacts, we'll add more contacts to the delete list:
            #  * Any current contact that's in the 'removed' state.
            #  * Any current non-removed contact that was in the list of contacts to remove.
            for existing_contact in existing_contacts_dict.itervalues():
                if existing_contact.IsRemoved(
                ) or existing_contact.contact_id in self._request_contact_ids:
                    self._contacts_to_delete.append(existing_contact)