Files
triangles_v5/src/notificationqueue.h
T
sami7777 e133e97f3b Add comprehensive RPC API upgrade: REST, ZMQ, SSE, address index
Phase 1 - New RPC commands (no new deps):
  - getblockheader: header data from memory, zero disk reads
  - estimatefee: static fee estimation (Bitcoin Core compatible)
  - getblockchaininfo: chain state, difficulty, moneysupply
  - getwalletinfo: balance, stake, txcount, keypool, encryption
  - getnetworkinfo: version, protocol, connections, proxy
  - gettxoutsetinfo: height, bestblock, total_amount

Phase 2 - REST API layer (-rest=1):
  - /rest/chaininfo.json, /rest/block/<hash>.json|hex
  - /rest/blockheader/<hash>.json, /rest/tx/<txid>.json|hex
  - /rest/blockhashbyheight/<n>, /rest/mempool.json
  - CORS headers for browser-based explorer access

Phase 3 - ZMQ pub/sub notifications (optional, USE_ZMQ=1):
  - Topics: hashblock, hashtx, rawblock, rawtx
  - Conditional compilation via ENABLE_ZMQ

Phase 4 - SSE real-time notifications (-ssenotify=1):
  - GET /events endpoint (authenticated, long-lived)
  - Block and transaction event streaming
  - 15-second keepalive for proxy compatibility

Phase 5 - Address index (-addressindex=1):
  - getaddressbalance, getaddressutxos, getaddresstxids
  - LevelDB-backed index updated in ConnectBlock/DisconnectBlock
  - Requires -reindex on first use

Also fixes QDesktopServices missing include for Qt5.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 00:50:34 -07:00

109 lines
3.1 KiB
C++

// Copyright (c) 2026 The Triangles developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef TRIANGLES_NOTIFICATIONQUEUE_H
#define TRIANGLES_NOTIFICATIONQUEUE_H
#include <string>
#include <deque>
#include <vector>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition_variable.hpp>
/**
* Thread-safe notification queue for SSE (Server-Sent Events) clients.
*
* Producers (block acceptance, mempool acceptance) push JSON event strings.
* Consumer threads (SSE HTTP handlers) wait on the condition variable and
* drain events as they arrive.
*
* The queue keeps the last MAX_QUEUED_EVENTS events so late-joining clients
* can get a small backlog. Each SSE client tracks its own read position.
*/
class CNotificationQueue
{
private:
mutable boost::mutex cs;
boost::condition_variable cond;
struct Event {
uint64_t id;
std::string data; // JSON payload
};
std::deque<Event> events;
uint64_t nNextId;
static const size_t MAX_QUEUED_EVENTS = 256;
public:
CNotificationQueue() : nNextId(1) {}
/** Push a new event. Wakes all waiting SSE clients. */
void Push(const std::string& strData)
{
boost::mutex::scoped_lock lock(cs);
events.push_back(Event{nNextId++, strData});
while (events.size() > MAX_QUEUED_EVENTS)
events.pop_front();
cond.notify_all();
}
/**
* Wait for events newer than nLastId.
* Returns new events and updates nLastId to the newest seen.
* Returns false if timed out with no new events, true if events were returned.
* Also returns false if fShutdown becomes true.
*/
bool WaitForEvents(uint64_t& nLastId, std::vector<std::string>& vEvents, int nTimeoutMs, const volatile bool& fShutdown)
{
vEvents.clear();
boost::mutex::scoped_lock lock(cs);
// Check for events already in the queue past our read position
bool fHasNew = false;
for (std::deque<Event>::const_iterator it = events.begin(); it != events.end(); ++it)
{
if (it->id > nLastId)
{
fHasNew = true;
break;
}
}
if (!fHasNew)
{
// Wait for new events or timeout
cond.timed_wait(lock, boost::posix_time::milliseconds(nTimeoutMs));
}
// Drain all events newer than nLastId
for (std::deque<Event>::const_iterator it = events.begin(); it != events.end(); ++it)
{
if (it->id > nLastId)
{
vEvents.push_back(it->data);
nLastId = it->id;
}
}
if (fShutdown)
return false;
return !vEvents.empty();
}
/** Get the current latest event ID (for clients that want to skip history). */
uint64_t GetLatestId() const
{
boost::mutex::scoped_lock lock(cs);
return nNextId - 1;
}
};
/** Global notification queue instance */
extern CNotificationQueue* pNotificationQueue;
#endif // TRIANGLES_NOTIFICATIONQUEUE_H