def at_most_every(_f=None, *, interval=60):
    """Call the wrapped function at most every `interval` seconds.

    Useful when `f` is (very) expensive to compute and you are happy
    to have results which are possibly a few seconds out of date.
    """
    last_time = time.monotonic() - interval - 1
    # use 'unset' singleton to indicate that last_result has not yet been cached
    last_result = unset = object()
    outstanding = None

    def caller(f):
        @wraps(f)
        async def wrapper(*args, **kwargs):
            nonlocal last_time, last_result, outstanding
            if outstanding is not None:
                # do not allow multiple concurrent calls, return an existing future
                return await outstanding
            now = time.monotonic()
            if last_result is unset or now > last_time + interval:
                outstanding = asyncio.ensure_future(f(*args, **kwargs))
                try:
                    last_result = await outstanding
                finally:
                    # complete, clear outstanding future and note the time
                    outstanding = None
                    last_time = time.monotonic()

            if last_result is unset:
                # this should be impossible, but make sure we don't return our no-result singleton
                raise RuntimeError("No cached result to return")

            return last_result

        return wrapper

    if _f is None:
        return caller
    else:
        return caller(_f)
Call the wrapped function at most every `interval` seconds.

    Useful when `f` is (very) expensive to compute and you are happy
    to have results which are possibly a few seconds out of date.
    
binderhub/health.py