Flush join indexes when memory is constrained

Add a separate limit for index memory usage that is independent of the task
memory limit. This removes the risk of the flushable memory usage causing
another operator to run out of memory.

Loader will attempt to load new data and add to existing cache.  If that
fails, it flushes the cache and tries again.  If that fails, it loads only
the single required request for the loader thread.
instead of adding your own request back in, i think it would be more clear to just re-enqueue requests that you didn't plan on processing.