mirror of
https://github.com/l5yth/potato-mesh.git
synced 2026-07-06 01:42:11 +02:00
d2fe4f8223
* web: add node opt-out marker and data retention policies * web: address review comments * web: address review comments
85 lines
3.2 KiB
Ruby
85 lines
3.2 KiB
Ruby
# Copyright © 2025-26 l5yth & contributors
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# frozen_string_literal: true
|
|
|
|
module PotatoMesh
|
|
module App
|
|
module Federation
|
|
# Count the number of nodes active since the supplied timestamp.
|
|
#
|
|
# Opted-out nodes (those whose +short_name+ or +long_name+ contains
|
|
# the {PotatoMesh::Config::NODE_OPT_OUT_MARKER}) are excluded so the
|
|
# federation node total never reflects nodes that have asked to stay
|
|
# hidden from API consumers.
|
|
#
|
|
# @param cutoff [Integer] unix timestamp in seconds.
|
|
# @param db [SQLite3::Database, nil] optional open handle to reuse.
|
|
# @return [Integer, nil] node count or nil when unavailable.
|
|
def active_node_count_since(cutoff, db: nil)
|
|
return nil unless cutoff
|
|
|
|
handle = db || open_database(readonly: true)
|
|
sql = "SELECT COUNT(*) FROM nodes WHERE last_heard >= ? AND #{opt_out_self_filter}"
|
|
count =
|
|
with_busy_retry do
|
|
handle.get_first_value(sql, [cutoff.to_i, *opt_out_marker_params])
|
|
end
|
|
Integer(count)
|
|
rescue SQLite3::Exception, ArgumentError => e
|
|
warn_log(
|
|
"Failed to count active nodes",
|
|
context: "instances.nodes_count",
|
|
error_class: e.class.name,
|
|
error_message: e.message,
|
|
)
|
|
nil
|
|
ensure
|
|
handle&.close unless db
|
|
end
|
|
|
|
# Count the number of nodes for a specific protocol active since the
|
|
# supplied timestamp. Opted-out nodes are excluded for the same
|
|
# reason as in {#active_node_count_since}.
|
|
#
|
|
# @param cutoff [Integer] unix timestamp in seconds.
|
|
# @param protocol [String] protocol name (e.g. "meshcore", "meshtastic").
|
|
# @param db [SQLite3::Database, nil] optional open handle to reuse.
|
|
# @return [Integer, nil] node count or nil when unavailable.
|
|
def active_node_count_since_for_protocol(cutoff, protocol, db: nil)
|
|
return nil unless cutoff && protocol
|
|
|
|
handle = db || open_database(readonly: true)
|
|
sql = "SELECT COUNT(*) FROM nodes WHERE last_heard >= ? AND protocol = ? AND #{opt_out_self_filter}"
|
|
count =
|
|
with_busy_retry do
|
|
handle.get_first_value(sql, [cutoff.to_i, protocol, *opt_out_marker_params])
|
|
end
|
|
Integer(count)
|
|
rescue SQLite3::Exception, ArgumentError => e
|
|
warn_log(
|
|
"Failed to count active nodes for protocol",
|
|
context: "instances.protocol_nodes_count",
|
|
protocol: protocol,
|
|
error_class: e.class.name,
|
|
error_message: e.message,
|
|
)
|
|
nil
|
|
ensure
|
|
handle&.close unless db
|
|
end
|
|
end
|
|
end
|
|
end
|