@@ -591,22 +591,16 @@ func (r *raft) quorumThreshold() int {
591591}
592592
593593func (r * raft ) materializeDecision (k uint64 , cid string ) (pb.Entry , bool ) {
594- // Prefer the exact payload we cached when receiving MsgFastProp on the leader.
595594 if m := r .proposalCache [k ]; m != nil {
596595 if e , ok := m [cid ]; ok {
597596 // Ensure leader-origin on install; Index/Term set by caller.
598597 e .Origin = pb .EntryOriginLeader .Enum ()
598+ e .Index , e .Term = 0 , 0
599599 return e , true
600600 }
601601 }
602- // Fallback: create a header-only entry with content_id; Data empty is OK
603- // (you may want to look up the full payload from app layer).
604- return pb.Entry {
605- Type : pb .EntryNormal ,
606- Data : nil ,
607- Origin : pb .EntryOriginLeader .Enum (),
608- ContentId : []byte (cid ),
609- }, true
602+ // No payload yet — do NOT synthesize an empty entry.
603+ return pb.Entry {}, false
610604}
611605
612606func (r * raft ) nullDuplicates (cid string , keepIdx uint64 ) {
@@ -1793,9 +1787,13 @@ func stepLeader(r *raft, m pb.Message) error {
17931787 bucket = make (map [string ]pb.Entry )
17941788 r .proposalCache [m .Index ] = bucket
17951789 }
1796- // Keep first payload we see for this (index,cid); ignore later duplicates .
1797- if _ , ok := bucket [ cid ]; ! ok {
1790+ // Leader-preferred caching: our own payload must win to preserve Header.ID .
1791+ if m . From == r . id {
17981792 bucket [cid ] = e
1793+ } else {
1794+ if _ , ok := bucket [cid ]; ! ok {
1795+ bucket [cid ] = e
1796+ }
17991797 }
18001798
18011799 // classic-fallback when mixed cluster can't produce fast-vote CQ.
0 commit comments