NewNode returns a new Node instance.
(rc *pb.RaftContext, store *raftwal.DiskStorage, tlsConfig *tls.Config)
| 80 | |
| 81 | // NewNode returns a new Node instance. |
| 82 | func NewNode(rc *pb.RaftContext, store *raftwal.DiskStorage, tlsConfig *tls.Config) *Node { |
| 83 | snap, err := store.Snapshot() |
| 84 | x.Check(err) |
| 85 | |
| 86 | n := &Node{ |
| 87 | StartTime: time.Now(), |
| 88 | Id: rc.Id, |
| 89 | MyAddr: rc.Addr, |
| 90 | Store: store, |
| 91 | Cfg: &raft.Config{ |
| 92 | ID: rc.Id, |
| 93 | ElectionTick: 20, // 2s if we call Tick() every 100 ms. |
| 94 | HeartbeatTick: 1, // 100ms if we call Tick() every 100 ms. |
| 95 | Storage: store, |
| 96 | MaxInflightMsgs: 256, |
| 97 | MaxSizePerMsg: 256 << 10, // 256 KB should allow more batching. |
| 98 | MaxCommittedSizePerReady: 64 << 20, // Avoid loading entire Raft log into memory. |
| 99 | // We don't need lease based reads. They cause issues because they |
| 100 | // require CheckQuorum to be true, and that causes a lot of issues |
| 101 | // for us during cluster bootstrapping and later. A seemingly |
| 102 | // healthy cluster would just cause leader to step down due to |
| 103 | // "inactive" quorum, and then disallow anyone from becoming leader. |
| 104 | // So, let's stick to default options. Let's achieve correctness, |
| 105 | // then we achieve performance. Plus, for the Dgraph alphas, we'll |
| 106 | // be soon relying only on Timestamps for blocking reads and |
| 107 | // achieving linearizability, than checking quorums (Zero would |
| 108 | // still check quorums). |
| 109 | ReadOnlyOption: raft.ReadOnlySafe, |
| 110 | // When a disconnected node joins back, it forces a leader change, |
| 111 | // as it starts with a higher term, as described in Raft thesis (not |
| 112 | // the paper) in section 9.6. This setting can avoid that by only |
| 113 | // increasing the term, if the node has a good chance of becoming |
| 114 | // the leader. |
| 115 | PreVote: true, |
| 116 | |
| 117 | // We can explicitly set Applied to the first index in the Raft log, |
| 118 | // so it does not derive it separately, thus avoiding a crash when |
| 119 | // the Applied is set to below snapshot index by Raft. |
| 120 | // In case this is a new Raft log, first would be 1, and therefore |
| 121 | // Applied would be zero, hence meeting the condition by the library |
| 122 | // that Applied should only be set during a restart. |
| 123 | // |
| 124 | // Update: Set the Applied to the latest snapshot, because it seems |
| 125 | // like somehow the first index can be out of sync with the latest |
| 126 | // snapshot. |
| 127 | Applied: snap.Metadata.Index, |
| 128 | |
| 129 | Logger: &x.ToGlog{}, |
| 130 | }, |
| 131 | // processConfChange etc are not throttled so some extra delta, so that we don't |
| 132 | // block tick when applyCh is full |
| 133 | Applied: y.WaterMark{Name: "Applied watermark"}, |
| 134 | RaftContext: rc, |
| 135 | //nolint:gosec // random node id generator does not require cryptographic precision |
| 136 | Rand: rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())}), |
| 137 | confChanges: make(map[uint64]chan error), |
| 138 | messages: make(chan sendmsg, 100), |
| 139 | peers: make(map[uint64]string), |