def cached_procedure(
    cache_file: str | None,
    payload_fn: Callable[..., str],
    cache_file_fn: Callable[[], str] | None = None,
):
    """Decorator to cache the runs of a procedure on disk. Procedures should not have
       a return value.

    Args:
        cache_file: The file to store the cache payload in.
        payload_fn: Function that computes cache payload from function args.
        cache_file_fn: Function that computes the cache file name at runtime.

    Returns:
        The decorated function.

    Raises:
        ValueError: If both cache_file and cache_file_fn are provided.
    """
    if cache_file and cache_file_fn is not None:
        msg = "cache_file and cache_file_fn cannot both be provided."
        raise ValueError(msg)

    def _inner_decorator(func: Callable):
        def _inner(*args, **kwargs):
            _cache_file = cache_file_fn() if cache_file_fn is not None else cache_file
            if not _cache_file:
                msg = "Unknown cache file, cannot cache result."
                raise ValueError(msg)
            payload = _read_cached_procedure_file(_cache_file)
            new_payload = payload_fn(*args, **kwargs)
            if payload != new_payload:
                _clear_cached_procedure_file(_cache_file)
                func(*args, **kwargs)
                _write_cached_procedure_file(new_payload, _cache_file)

        return _inner

    return _inner_decorator
Decorator to cache the runs of a procedure on disk. Procedures should not have
       a return value.

    Args:
        cache_file: The file to store the cache payload in.
        payload_fn: Function that computes cache payload from function args.
        cache_file_fn: Function that computes the cache file name at runtime.

    Returns:
        The decorated function.

    Raises:
        ValueError: If both cache_file and cache_file_fn are provided.
    
reflex/utils/prerequisites.py