mirror of
https://github.com/l5yth/potato-mesh.git
synced 2026-10-31 03:51:58 +01:00
Co-authored-by: oregonknuths <159513803+oregonknuths@users.noreply.github.com>
This commit is contained in:
1 parent
40dfa14dfa
commit
ace03b6807
37 files changed
+1022
-178
No files matched your search
@@ -212,6 +212,30 @@ module PotatoMesh
|
||||
nil
|
||||
end
|
||||
|
||||
# Decide whether an incoming node record collides with a stored row of a
|
||||
# different protocol and must therefore be skipped (the cross-protocol
|
||||
# node-row hijack guard in {#upsert_node}).
|
||||
#
|
||||
# A stored +"meshtastic"+ value doubles as the schema default stamped on
|
||||
# rows ingested before their protocol was known, so a +"meshcore"+
|
||||
# record may still reclaim such a row — the established bug #747
|
||||
# self-heal that the upsert's +NULLIF(nodes.protocol,'meshtastic')+
|
||||
# conflict clause implements. Every other differing pairing between two
|
||||
# known protocols is a genuine 4-byte id collision across protocols and
|
||||
# is rejected.
|
||||
#
|
||||
# @param stored_protocol [String, nil] protocol currently on the row, or
|
||||
# nil when no row exists yet.
|
||||
# @param incoming_protocol [String] resolved protocol of the incoming
|
||||
# record.
|
||||
# @return [Boolean] true when the record must be skipped.
|
||||
def cross_protocol_conflict?(stored_protocol, incoming_protocol)
|
||||
return false unless KNOWN_PROTOCOLS.include?(stored_protocol)
|
||||
return false if stored_protocol == incoming_protocol
|
||||
return false if stored_protocol == "meshtastic" && incoming_protocol == "meshcore"
|
||||
true
|
||||
end
|
||||
|
||||
# Insert or update a node row from an inbound NodeInfo-style payload.
|
||||
#
|
||||
# Two-phase write. Phase one is the freshness-guarded upsert: a record
|
||||
@@ -268,6 +292,35 @@ module PotatoMesh
|
||||
end
|
||||
node_num = resolve_node_num(node_id, n)
|
||||
|
||||
# Cross-protocol node-row hijack guard. +nodes.node_id+ is a global
|
||||
# TEXT primary key shared by every protocol's id mapping, and both the
|
||||
# MeshCore and Reticulum mappings truncate a native identifier to its
|
||||
# first 4 bytes — so two nodes on *different* protocols can collide on
|
||||
# one +node_id+. Without this guard the colliding record would pass
|
||||
# the freshness guard below (Reticulum announces stamp a wall-clock
|
||||
# +lastHeard+) and overwrite the stored row's fields wholesale, with
|
||||
# the row's protocol either flipped or silently mismatched. Skip such
|
||||
# records entirely; neither row's data may corrupt the other's.
|
||||
# Same-protocol prefix collisions remain the accepted MeshCore-
|
||||
# inherited merge behaviour (see CONTRACTS.md, "Reticulum node id
|
||||
# mapping"), and a stored default-'meshtastic' row may still be
|
||||
# reclaimed by a meshcore record (the #747 self-heal preserved by
|
||||
# +cross_protocol_conflict?+).
|
||||
stored_protocol = db.get_first_value(
|
||||
"SELECT protocol FROM nodes WHERE node_id = ? LIMIT 1",
|
||||
[node_id],
|
||||
)
|
||||
if cross_protocol_conflict?(stored_protocol, protocol)
|
||||
debug_log(
|
||||
"Skipped cross-protocol node upsert",
|
||||
context: "data_processing.upsert_node",
|
||||
node_id: node_id,
|
||||
stored_protocol: stored_protocol,
|
||||
incoming_protocol: protocol,
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
# The prometheus helper still receives the raw `pos` so that gauges
|
||||
# not affected by sentinel handling (e.g. precision_bits) keep
|
||||
# updating; the latitude/longitude guards inside +update_prometheus_metrics+
|
||||
|
||||
Reference in new issue
Block a user