code: def scan_file(fullpath, relpath, assign_id):
      
  
      logger.debug("Scanning file: %s (%s) %s", fullpath, relpath, assign_id)
  
      def do_scan():
          """ helper function to do the scan and gather the result """
          _, ext = os.path.splitext(fullpath)
  
          try:
              if ext in ENTRY_TYPES:
                  logger.info("Scanning entry: %s", fullpath)
                  return entry.scan_file(fullpath, relpath, assign_id)
  
              if ext in CATEGORY_TYPES:
                  logger.info("Scanning meta info: %s", fullpath)
                  return category.scan_file(fullpath, relpath)
  
              return None
          except:  # pylint: disable=bare-except
              logger.exception("Got error parsing %s", fullpath)
              return False
  
      result = do_scan()
      if result is False and not assign_id:
          logger.info("Scheduling fixup for %s", fullpath)
          THREAD_POOL.submit(scan_file, fullpath, relpath, True)
      else:
          logger.debug("%s complete", fullpath)
          if result:
              set_fingerprint(fullpath)
          SCHEDULED_FILES.remove(fullpath)
docs: Scan a file for the index
  
      fullpath -- The full path to the file
      relpath -- The path to the file, relative to its base directory
      assign_id -- Whether to assign an ID to the file if not yet assigned
  
      This calls into various modules' scanner functions; the expectation is that
      the scan_file function will return a truthy value if it was scanned
      successfully, False if it failed, and None if there is nothing to scan.