def test_works(self):
        with open(self.path, 'w') as f:
            json.dump({'A': 'a'}, f)

        r = file_reader.FileReaderThread(self.path, 0.1)
        r.start()
        try:
            self.assertEqual(r.last_value, {'A': 'a'})

            # Change the file. Expect possible conflict on Windows.
            attempt = 0
            bytes_json = json.dumps({'B': 'b'}).encode('utf-8')
            while True:
                try:
                    file_path.atomic_replace(self.path, bytes_json)
                    break
                except OSError:
                    attempt += 1
                    if attempt == 20:
                        self.fail('Cannot replace the file, giving up')
                    time.sleep(0.05)

            # Give some reasonable time for the reader thread to pick up the change.
            # This test will flake if for whatever reason OS thread scheduler is
            # lagging for more than 2 seconds.
            time.sleep(2)

            self.assertEqual(r.last_value, {'B': 'b'})
        finally:
            r.stop()
Пример #2
0
 def test_atomic_replace_existing_file(self):
   path = os.path.join(self.tempdir, 'existing_file')
   with open(path, 'wb') as f:
     f.write('existing body')
   file_path.atomic_replace(path, 'new body')
   with open(path, 'rb') as f:
     self.assertEqual('new body', f.read())
   self.assertEqual([u'existing_file'], os.listdir(self.tempdir))
Пример #3
0
    def _dump(self):
        """Attempts to rewrite the file, retrying a bunch of times.

    Returns:
      True to carry on, False to exit the thread.
    """
        try:
            blob = json.dumps(self._producer_callback(),
                              sort_keys=True,
                              indent=2,
                              separators=(',', ': '))
        except Exception:
            logging.exception('Unexpected exception in the callback')
            return True
        if blob == self._last_dumped_blob:
            return True  # already have it on disk
        logging.info('Updating %s', self._path)

        # On Windows the file may be locked by reading process. Don't freak out,
        # just retry a bit later.
        attempts = 100
        while True:
            try:
                file_path.atomic_replace(self._path, blob)
                self._last_dumped_blob = blob
                return True  # success!
            except (IOError, OSError) as e:
                logging.error('Failed to update the file: %s', e)
            if not attempts:
                logging.error(
                    'Failed to update the file %s after many attempts, giving up',
                    self._path)
                return True
            attempts -= 1
            if not self._wait(0.05):
                return False
Пример #4
0
 def test_atomic_replace_new_file(self):
   path = os.path.join(self.tempdir, 'new_file')
   file_path.atomic_replace(path, 'blah')
   with open(path, 'rb') as f:
     self.assertEqual('blah', f.read())
   self.assertEqual([u'new_file'], os.listdir(self.tempdir))