generated from duckdb/extension-template
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
281 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#include "discovery.hpp" | ||
#include "mbedtls_wrapper.hpp" | ||
#include "duckdb/common/common.hpp" | ||
#include <chrono> | ||
#include <iostream> | ||
|
||
namespace duckdb { | ||
|
||
// Static member definition | ||
std::unique_ptr<PeerDiscovery> PeerDiscovery::instance = nullptr; | ||
|
||
// Constructor implementation | ||
PeerDiscovery::PeerDiscovery(DatabaseInstance& database) : db(database) { | ||
initTables(); | ||
} | ||
|
||
void PeerDiscovery::Initialize(DatabaseInstance& db) { | ||
instance = std::unique_ptr<PeerDiscovery>(new PeerDiscovery(db)); | ||
} | ||
|
||
void PeerDiscovery::initTables() { | ||
Connection conn(db); | ||
conn.Query("CREATE TABLE IF NOT EXISTS peers (" | ||
"hash VARCHAR, peer_id VARCHAR, name VARCHAR, endpoint VARCHAR," | ||
"source_address VARCHAR, ttl BIGINT, metadata VARCHAR," | ||
"registered_at TIMESTAMP, PRIMARY KEY (hash, peer_id))"); | ||
|
||
conn.Query("CREATE INDEX IF NOT EXISTS idx_peers_ttl ON peers(registered_at, ttl)"); | ||
} | ||
|
||
std::string PeerDiscovery::generateDeterministicId(const std::string& name, const std::string& endpoint) { | ||
std::string combined = name + ":" + endpoint; | ||
hash_bytes hash; | ||
duckdb_mbedtls::MbedTlsWrapper::ComputeSha256Hash(combined.c_str(), combined.length(), (char*)hash); | ||
|
||
std::string result; | ||
for (int i = 0; i < 16; i++) { | ||
char buf[3]; | ||
snprintf(buf, sizeof(buf), "%02x", hash[i]); | ||
result += buf; | ||
} | ||
return result; | ||
} | ||
|
||
|
||
void PeerDiscovery::registerPeer(const std::string& hash, const PeerData& data) { | ||
Connection conn(db); | ||
std::string peerId = generateDeterministicId(data.name, data.endpoint); | ||
|
||
auto stmt = conn.Prepare( | ||
"INSERT INTO peers (hash, peer_id, name, endpoint, source_address, ttl, metadata, registered_at) " | ||
"VALUES ($1, $2, $3, $4, $5, $6, $7, CURRENT_TIMESTAMP)"); | ||
|
||
vector<Value> params; | ||
params.push_back(Value(hash)); | ||
params.push_back(Value(peerId)); | ||
params.push_back(Value(data.name)); | ||
params.push_back(Value(data.endpoint)); | ||
params.push_back(Value(data.sourceAddress)); | ||
params.push_back(Value::BIGINT(data.ttl)); | ||
params.push_back(Value(data.metadata)); | ||
|
||
stmt->Execute(params); | ||
} | ||
|
||
std::unique_ptr<MaterializedQueryResult> PeerDiscovery::getPeers(const std::string& hash, bool ndjson) { | ||
Connection conn(db); | ||
auto stmt = conn.Prepare( | ||
"SELECT name, endpoint, source_address as sourceAddress, " | ||
"peer_id as peerId, metadata, " | ||
"CAST(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - registered_at)) AS INTEGER) as age, " | ||
"ttl FROM peers WHERE hash = $1 AND " | ||
"EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - registered_at)) < ttl " | ||
"ORDER BY age ASC"); | ||
|
||
vector<Value> params; | ||
params.push_back(Value(hash)); | ||
|
||
auto result = stmt->Execute(params); | ||
return unique_ptr<MaterializedQueryResult>((MaterializedQueryResult*)result.release()); | ||
} | ||
|
||
void PeerDiscovery::removePeer(const std::string& hash, const std::string& peerId) { | ||
Connection conn(db); | ||
auto stmt = conn.Prepare("DELETE FROM peers WHERE hash = $1 AND peer_id = $2"); | ||
stmt->Execute(hash, peerId); | ||
} | ||
|
||
void PeerDiscovery::updateHeartbeat(const std::string& hash, const std::string& peerId) { | ||
Connection conn(db); | ||
auto stmt = conn.Prepare("UPDATE peers SET registered_at = CURRENT_TIMESTAMP " | ||
"WHERE hash = $1 AND peer_id = $2"); | ||
stmt->Execute(hash, peerId); | ||
} | ||
|
||
void PeerDiscovery::cleanupExpired() { | ||
Connection conn(db); | ||
conn.Query("DELETE FROM peers WHERE EXTRACT(EPOCH FROM " | ||
"(CURRENT_TIMESTAMP - registered_at)) >= ttl"); | ||
} | ||
|
||
} // namespace duckdb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#pragma once | ||
|
||
#include "duckdb.hpp" | ||
#include "duckdb/common/types.hpp" | ||
#include <memory> | ||
#include <string> | ||
|
||
namespace duckdb { | ||
|
||
using hash_bytes = uint8_t[32]; | ||
|
||
struct PeerData { | ||
std::string name; | ||
std::string endpoint; | ||
std::string sourceAddress; | ||
int64_t ttl; | ||
std::string metadata; | ||
}; | ||
|
||
class PeerDiscovery { | ||
static std::unique_ptr<PeerDiscovery> instance; | ||
DatabaseInstance& db; | ||
|
||
void initTables(); | ||
PeerDiscovery(DatabaseInstance& database); | ||
|
||
public: | ||
static void Initialize(DatabaseInstance& db); | ||
static PeerDiscovery& Instance() { return *instance; } | ||
static std::string generateDeterministicId(const std::string& name, const std::string& endpoint); | ||
|
||
void registerPeer(const std::string& hash, const PeerData& data); | ||
std::unique_ptr<MaterializedQueryResult> getPeers(const std::string& hash, bool ndjson = false); | ||
void removePeer(const std::string& hash, const std::string& peerId); | ||
void updateHeartbeat(const std::string& hash, const std::string& peerId); | ||
void cleanupExpired(); | ||
}; | ||
|
||
} // namespace duckdb |