@gen.coroutine
  def _Check(self):
    """Gathers pre-mutation information:
       1. Queries for existing followers and viewpoint.
       2. Checkpoints list of followers that need to be revived.
       3. Checkpoints list of contacts that need to be made prospective users.
       4. Checkpoints list of contacts that are already following the viewpoint.

       Validates the following:
       1. Max follower limit.
       2. Permission to add followers.
    """
    # Get the viewpoint to be modified, along with the follower that is adding the additional users.
    # This state will not be changed by add followers, and so doesn't need to be part of the checkpoint.
    self._viewpoint, self._follower = yield gen.Task(Viewpoint.QueryWithFollower,
                                                     self._client,
                                                     self._user_id,
                                                     self._viewpoint_id)

    # Checks permission to add followers.
    if self._follower is None or not self._follower.CanContribute():
      raise PermissionError('User %d does not have permission to add followers to viewpoint "%s".' %
                            (self._user_id, self._viewpoint_id))

    # Start populating the checkpoint if this the first time the operation has been run.
    if self._op.checkpoint is None:
      # Get all existing followers.
      self._existing_followers, _ = yield gen.Task(Viewpoint.QueryFollowers,
                                                   self._client,
                                                   self._viewpoint_id,
                                                   limit=Viewpoint.MAX_FOLLOWERS)

      # Get list of followers which have removed themselves from the viewpoint and will need to be revived.
      self._revive_follower_ids = self._GetRevivableFollowers(self._existing_followers)

      # Get a tuple for each contact: (user_exists?, user_id, webapp_dev_id). 
      self._contact_ids = yield self._ResolveContactIds(self._contact_dicts)

      # Set checkpoint.
      # Existing followers, followers to revive, and list of contacts need to be check-pointed
      # because these sets are changed in the UPDATE phase. If we fail after UPDATE, but before
      # NOTIFY, we would not send correct notifications on retry.
      checkpoint = {'existing': [follower.user_id for follower in self._existing_followers],
                    'revive': self._revive_follower_ids,
                    'contacts': self._contact_ids}
      yield self._op.SetCheckpoint(self._client, checkpoint)
    else:
      # Restore state from checkpoint.
      follower_keys = [DBKey(follower_id, self._viewpoint_id) for follower_id in self._op.checkpoint['existing']]
      self._existing_followers = yield gen.Task(Follower.BatchQuery, self._client, follower_keys, None)
      self._revive_follower_ids = self._op.checkpoint['revive']
      self._contact_ids = self._op.checkpoint['contacts']

    self._contact_user_ids = [user_id for user_exists, user_id, webapp_dev_id in self._contact_ids]

    # Check if we're about to exceed follower limit on this viewpoint.
    if len(self._existing_followers) + len(self._contact_dicts) > Viewpoint.MAX_FOLLOWERS:
      raise LimitExceededError(
        'User %d attempted to exceed follower limit on viewpoint "%s" by adding %d followers.' %
        (self._user_id, self._viewpoint_id, len(self._contact_dicts)))
dataset/ETHPy150Open viewfinderco/viewfinder/backend/op/add_followers_op.py/AddFollowersOperation._Check/original