def METHOD_NAME(
  path_details: Iterable[Tuple[str, Optional[PathDetails]]],
  database: Database,
  handlers: Tuple[Callable],
  logger: Logger
  ):
  """Upload CSVs to the database and archive them using the specified handlers.
  :path_details: output from CsvImporter.find*_csv_files
  :database: an open connection to the epidata database
  :handlers: functions for archiving (successful, failed) files
  :return: the number of modified rows
  """
  archive_as_successful, archive_as_failed = handlers
  total_modified_row_count = 0
  # iterate over each file
  for path, details in path_details:
    logger.info(event='handling', dest=path)
    path_src, filename = os.path.split(path)
    # file path or name was invalid, source is unknown
    if not details:
      archive_as_failed(path_src, filename, 'unknown',logger)
      continue
    csv_rows = CsvImporter.load_csv(path, details)
    rows_list = list(csv_rows)
    all_rows_valid = rows_list and all(r is not None for r in rows_list)
    if all_rows_valid:
      try:
        modified_row_count = database.insert_or_update_bulk(rows_list)
        logger.info(f"insert_or_update_bulk {filename} returned {modified_row_count}")
        logger.info(
          "Inserted database rows",
          row_count = modified_row_count,
          source = details.source,
          signal = details.signal,
          geo_type = details.geo_type,
          time_value = details.time_value,
          issue = details.issue,
          lag = details.lag
        )
        if modified_row_count is None or modified_row_count: # else would indicate zero rows inserted
          total_modified_row_count += (modified_row_count if modified_row_count else 0)
          database.commit()
      except DBLoadStateException as e:
        # if the db is in a state that is not fit for loading new data,
        # then we should stop processing any more files
        raise e
      except Exception as e:
        all_rows_valid = False
        logger.exception('exception while inserting rows', exc_info=e)
        database.rollback()
    # archive the current file based on validation results
    if all_rows_valid:
      archive_as_successful(path_src, filename, details.source, logger)
    else:
      archive_as_failed(path_src, filename, details.source, logger)
  return total_modified_row_count