code: func (w *projectionWorker) run(ctx context.Context) {
  	var output *projectionOutput
  	defer func() {
  		if r := recover(); r != nil {
  			recoveryProjection(output, r)
  		}
  	}()
  	for {
  		input := readProjectionInput(w.inputCh, w.globalFinishCh)
  		if input == nil {
  			return
  		}
  
  		output = readProjectionOutput(w.outputCh, w.globalFinishCh)
  		if output == nil {
  			return
  		}
  
  		err := w.evaluatorSuit.Run(w.sctx, input.chk, output.chk)
  		output.done <- err
  
  		if err != nil {
  			return
  		}
  
  		w.inputGiveBackCh <- input
  	}
  }
docs: // run gets projectionWorker's input and output resources from its
  // "inputCh" and "outputCh" channel, once the input and output resources are
  // abtained, it calculate the projection result use "input.chk" as the input
  // and "output.chk" as the output, once the calculation is done, it:
  //   a. Sends "nil" or error to "output.done" to mark this input is finished.
  //   b. Returns the "input" resource to "projectionInputFetcher.inputCh".
  //
  // It is finished and exited once:
  //   a. "ProjectionExec" closes the "globalFinishCh".