class_docstr: A bucket containing up to :size: of DHTIDs in [lower, upper) semi-interval.
  Maps DHT node ids to their peer_ids
class_docstr_tok: ["A","bucket","containing","up","to",":","size",":","of","DHTIDs","in","[","lower",",","upper",")","semi-interval",".","Maps","DHT","node","ids","to","their","peer_ids"]
docstr: Add node to KBucket or update existing node, return True if successful, False if the bucket is full.
  If the bucket is full, keep track of node in a replacement list, per section 4.1 of the paper.
  
  :param node_id: dht node identifier that should be added or moved to the front of bucket
  :param peer_id: network address associated with that node id
  :note: this function has a side-effect of resetting KBucket.last_updated time
docstr_tok: ["Add","node","to","KBucket","or","update","existing","node",",","return","True","if","successful",",","False","if","the","bucket","is","full",".","If","the","bucket","is","full",",","keep","track","of","node","in","a","replacement","list",",","per","section","4.1","of","the","paper",".",":","param","node_id",":","dht","node","identifier","that","should","be","added","or","moved","to","the","front","of","bucket",":","param","peer_id",":","network","address","associated","with","that","node","id",":","note",":","this","function","has","a","side-effect","of","resetting","KBucket.last_updated","time"]
code: def add_or_update_node(self, node_id: DHTID, peer_id: PeerID) -> bool:
      """
      Add node to KBucket or update existing node, return True if successful, False if the bucket is full.
      If the bucket is full, keep track of node in a replacement list, per section 4.1 of the paper.
  
      :param node_id: dht node identifier that should be added or moved to the front of bucket
      :param peer_id: network address associated with that node id
      :note: this function has a side-effect of resetting KBucket.last_updated time
      """
      if node_id in self.nodes_requested_for_ping:
          self.nodes_requested_for_ping.remove(node_id)
      self.last_updated = get_dht_time()
      if node_id in self.nodes_to_peer_id:
          del self.nodes_to_peer_id[node_id]
          self.nodes_to_peer_id[node_id] = peer_id
      elif len(self.nodes_to_peer_id) < self.size:
          self.nodes_to_peer_id[node_id] = peer_id
      else:
          if node_id in self.replacement_nodes:
              del self.replacement_nodes[node_id]
          self.replacement_nodes[node_id] = peer_id
          return False
      return True
  
imports: from __future__ import annotations
  import hashlib
  import heapq
  import os
  import random
  from collections.abc import Iterable
  from itertools import chain
  from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Union
  from hivemind.p2p import PeerID
  from hivemind.utils import MSGPackSerializer, get_dht_time
label_desc: Use image node_id 3 for calling the KBucket obj's underlying member method code with example usage: obj.add_or_update_node(node_id, peer_id) and returns: True, False