func (n *node) ProposeAndWait(ctx context.Context, proposal *task.Proposal) error { if n.raft == nil { return x.Errorf("RAFT isn't initialized yet") } proposal.Id = rand.Uint32() slice := slicePool.Get().([]byte) if len(slice) < proposal.Size() { slice = make([]byte, proposal.Size()) } defer slicePool.Put(slice) upto, err := proposal.MarshalTo(slice) if err != nil { return err } proposalData := slice[:upto] che := make(chan error, 1) n.props.Store(proposal.Id, che) if err = n.raft.Propose(ctx, proposalData); err != nil { return x.Wrapf(err, "While proposing") } // Wait for the proposal to be committed. if proposal.Mutations != nil { x.Trace(ctx, "Waiting for the proposal: mutations.") } else { x.Trace(ctx, "Waiting for the proposal: membership update.") } select { case err = <-che: x.TraceError(ctx, err) return err case <-ctx.Done(): return ctx.Err() } }