openlang

Does start_link returning mean the cache is warm?

start_link has a reassuring name, but what has the client actually learned when it returns?

Here init returns {:ok, state, {:continue, :warm_cache}}. The startup call waits for init and nothing more. Warming happens afterwards in handle_continue. So the acknowledgement means the process exists, not that the cache is warm. Client requests won't run concurrently with the continuation inside this GenServer. They just line up behind it.

Now try the word ready on that. A client sees a healthy startup indicator and immediately asks for a cached value. If the indicator only means init returned, ready is promising too much.

There are two honest options. Hold readiness until warming finishes. Or expose Warming and bound how many requests may wait, which brings its own question about what a timeout removes from the pending work.

A supervised restart lands in the same spot. Restarting the process and restoring a usable cache are two different promises. Ready should name the one the client came for. Started is a perfectly good word for the other.

后续讨论 4

顺着彼此的依据读下去
  1. 固定链接

    Maybe the service doesn't have to hold anything. If clients already understand Warming, report it through readiness and let each one retry under its own limit. That's one less queue to explain, and this one would only exist to get through startup. If some client really can't retry, fine, add the wait. Give it a capacity and write down what a full queue tells the next caller, so saturation gets an answer right away instead of a hang.

  2. 固定链接

    The waiting option has two events to order, the caller's timeout and the removal of its pending request. The caller times out. Warming finishes. The server goes through its waiting entries and replies to this one before it gets to the withdrawal message. What happens then has to be defined.

    Move the withdrawal one step earlier and it reaches the server while warming is still running. Then the server has to find that caller's entry and drop it, so every entry needs a reference the withdrawal can name. In the first order the caller has the work instead. It gets a reply to a request it gave up on and has to recognize it and throw it away. Both orders need handling, and the waiting set still needs its own bound.

  3. 固定链接

    Go is what I'd reach for here, and there a ready channel covers both of Vadim's cases. The warm-up goroutine closes it when it finishes, and a readiness check is a non-blocking receive.

    go func() {
    	warm(cache)
    	close(ready)
    }()
    
    select {
    case <-ready:
    	// serve from the cache
    default:
    	// report Warming
    }

    Anyone who wants to wait just receives. A closed channel releases every receiver at once. The waiting set is then blocked goroutines, which is fine until request handlers pile up behind it, and then you're back at the capacity question.

  4. 固定链接

    A call that arrives during warming just waits. init returns the continue, and the continue runs before the server reads its mailbox, so a GenServer.call(pid, :get) sent right after start_link returns comes back once warming finishes. Stretch the warming past the default timeout and the call exits instead.

    So started really is the honest word for what start_link promised. The timeout is the only thing that tells the client the difference, and a timeout is a sad path, not a status. I'm back to wanting Warming as an answer the server gives.

同一个问题的其他角度

  1. Workers stuck on the results send after the context is canceled

    Ran into a simple thing and spent longer on it than I'd like. A pool of eight workers reads tasks from jobs and writes result…

    回复 8最近活动 go
  2. Eight queue slots can still leave 88 goroutines waiting

    A buffered channel bounds the jobs sitting in it. It does nothing about the goroutines blocked trying to send. Say a server g…

    回复 8最近活动 go
  3. Marking the filter async did nothing for the freeze

    Search filters a list of around forty thousand rows, and the UI freezes for a moment on every query. I figured async was the…

    回复 8最近活动 dart