def _update(self, contracts):
        updated = set()
        retry = set()

        try:
            with self.updating_counter(len(contracts)):
                start = time.clock()

                hashes = [c.hash for c in contracts]

                url = '{0}/challenge/{1}'.format(self.api_url,
                                                 self.token)

                data = {
                    'hashes': hashes
                }
                headers = {
                    'Content-Type': 'application/json'
                }
                try:
                    resp = self.session.post(url,
                                             data=json.dumps(data),
                                             headers=headers,
                                             verify=self.requests_verify_arg)
                except:
                    raise DownstreamError('Unable to perform HTTP post.')

                try:
                    r_json = handle_json_response(resp)
                except:
                    raise DownstreamError('Challenge update failed.')

                if 'challenges' not in r_json:
                    raise DownstreamError('Malformed response from server.')

                # challenges is in r_json
                challenges = r_json['challenges']

                for challenge in challenges:
                    if ('file_hash' not in challenge):
                        raise DownstreamError(
                            'Malformed response from server.')

                    try:
                        contract = self.contracts[challenge['file_hash']]
                    except __HOLE__:
                        self.logger.warn('Unexpected challenge update.')
                        continue

                    if ('error' in challenge or 'status' in challenge):
                        if 'error' in challenge:
                            message = challenge['error']
                        else:
                            message = challenge['status']
                        self.logger.error('Couldn\'t update contract {0}: {1}'
                                          .format(contract, message))
                        continue

                    for k in ['challenge', 'due', 'answered']:
                        if (k not in challenge):
                            self.logger.error(
                                'Malformed challenge for contract {0}'
                                .format(contract))
                            continue

                    if (challenge['answered']):
                        # contract didn't get updated
                        # we must have tried too early
                        # put it in the retry set
                        retry.add(contract)
                        continue

                    contract.challenge = self.heartbeat.challenge_type().\
                        fromdict(challenge['challenge'])
                    contract.expiration = datetime.utcnow()\
                        + timedelta(seconds=int(challenge['due']))
                    contract.answered = challenge['answered']

                    updated.add(contract)

                    # go ahead and begin proving now to save time
                    self._prove_async(contract)

                stop = time.clock()

                self.logger.info('Updated {0} contracts in {1} seconds'
                                 .format(len(updated), round(stop - start, 3)))
        except:
            # some issue updating... retry
            self.logger.error('Update error: {0}'.format(sys.exc_info()[1]))
            # we had an issue updating these contracts
            # we shall retry until they expire... then they'll
            # get dropped
            retry = set(contracts) - updated

        earliest = None
        reupdate_time = datetime.utcnow() \
            + timedelta(seconds=self.retry_interval)
        ready_time = datetime.utcnow()
        for c in contracts:
            if (c in retry and
                    c.expiration + c.estimated_interval > reupdate_time):
                self.update_queue.put(c, reupdate_time, ready_time)
                continue
            if (c in updated):
                if (earliest is None or c.expiration < earliest):
                    earliest = c.expiration
                continue
            # otherwise, remove the contract
            self.logger.error('Contract {0} not updated, dropping'
                              .format(c))
            self._remove_contract(c)

        if (earliest is not None):
            self.logger.debug('Earliest updated contract due in {0} '
                              'seconds'
                              .format((earliest - datetime.utcnow())
                                      .total_seconds()))

        if (len(retry) > 0):
            self.heartbeat_thread.wake()
dataset/ETHPy150Open StorjOld/downstream-farmer/downstream_farmer/client.py/DownstreamClient._update