177 lines
8.6 KiB
C
177 lines
8.6 KiB
C
#ifndef DB_OPS_H
|
|
#define DB_OPS_H
|
|
|
|
#include <stddef.h>
|
|
#include <time.h>
|
|
#include <cjson/cJSON.h>
|
|
|
|
// Generic helpers
|
|
int db_init(const char* connection_string);
|
|
void db_close(void);
|
|
int db_is_available(void);
|
|
const char* db_last_error(void);
|
|
const char* db_get_database_path(void);
|
|
|
|
// Per-thread connection override (used by thread pool workers)
|
|
int db_set_thread_connection(void* connection);
|
|
void db_clear_thread_connection(void);
|
|
|
|
// Worker/runtime SQLite connection lifecycle (kept internal to db_ops.c)
|
|
int db_open_worker_connection(const char* db_path, void** out_connection);
|
|
void db_close_worker_connection(void* connection);
|
|
|
|
// LISTEN/NOTIFY support for worker connections (PostgreSQL-only; SQLite stubs
|
|
// return -1 so callers can fall back to timer-based polling).
|
|
// db_worker_listen: issue LISTEN <channel> on the given worker connection.
|
|
// db_worker_poll_notify: block up to timeout_ms waiting for a notification on
|
|
// the given worker connection. Returns 1 if a notification was consumed,
|
|
// 0 on timeout, -1 on error/unsupported backend.
|
|
int db_worker_listen(void* connection, const char* channel);
|
|
int db_worker_poll_notify(void* connection, int timeout_ms);
|
|
// db_worker_poll_notify_with_payload: like db_worker_poll_notify but also
|
|
// returns the notification payload and channel via out params. The caller
|
|
// must free *out_payload and *out_channel (both NULL on timeout/error).
|
|
// Returns 1 if a notification was consumed, 0 on timeout, -1 on error.
|
|
int db_worker_poll_notify_with_payload(void* connection, int timeout_ms,
|
|
char** out_channel, char** out_payload);
|
|
|
|
// DB result codes (backend-agnostic)
|
|
#define DB_OK 0
|
|
#define DB_ERROR 1
|
|
#define DB_CONSTRAINT 19
|
|
#define DB_MISUSE 21
|
|
#define DB_ROW 100
|
|
#define DB_DONE 101
|
|
|
|
typedef struct db_stmt db_stmt_t;
|
|
|
|
// Generic statement helpers (Phase 1 migration)
|
|
int db_prepare(const char* sql, db_stmt_t** out_stmt);
|
|
int db_bind_text_param(db_stmt_t* stmt, int index, const char* value);
|
|
int db_bind_int_param(db_stmt_t* stmt, int index, int value);
|
|
int db_bind_int64_param(db_stmt_t* stmt, int index, long long value);
|
|
int db_step_stmt(db_stmt_t* stmt);
|
|
int db_reset_stmt(db_stmt_t* stmt);
|
|
const char* db_column_text_value(db_stmt_t* stmt, int col);
|
|
int db_column_int_value(db_stmt_t* stmt, int col);
|
|
long long db_column_int64_value(db_stmt_t* stmt, int col);
|
|
double db_column_double_value(db_stmt_t* stmt, int col);
|
|
void db_finalize_stmt(db_stmt_t* stmt);
|
|
|
|
// Subscription logging
|
|
int db_log_subscription_created(const char* sub_id, const char* wsi_ptr,
|
|
const char* client_ip, const char* filter_json);
|
|
int db_log_subscription_closed(const char* sub_id, const char* client_ip);
|
|
int db_log_subscription_disconnected(const char* client_ip);
|
|
int db_update_subscription_events_sent(const char* sub_id, int events_sent);
|
|
int db_cleanup_orphaned_subscriptions(void);
|
|
|
|
// NIP-09 event deletion helpers
|
|
int db_get_event_pubkey(const char* event_id, char* pubkey_out, size_t pubkey_out_size);
|
|
int db_delete_event_by_id(const char* event_id, const char* requester_pubkey);
|
|
int db_delete_events_by_address(const char* pubkey, int kind,
|
|
const char* d_tag, long before_timestamp);
|
|
// Combined exists + tombstone check for the ingest fast path (NIP-09)
|
|
int db_event_id_status(const char* event_id, int* out_exists, int* out_tombstoned);
|
|
|
|
// Auth rule checks for request validator
|
|
int db_is_pubkey_blacklisted(const char* pubkey);
|
|
int db_is_hash_blacklisted(const char* resource_hash);
|
|
int db_is_pubkey_whitelisted(const char* pubkey);
|
|
int db_count_active_whitelist_rules(void);
|
|
|
|
// Generic prepared COUNT helper
|
|
int db_count_with_sql(const char* sql, const char** bind_params, int bind_param_count, int* out_count);
|
|
char* db_execute_readonly_query_json(const char* query, const char* request_id,
|
|
char* error_message, size_t error_size,
|
|
int max_rows, int timeout_ms);
|
|
|
|
// Monitoring/stat helpers (Phase 1 api.c migration)
|
|
int db_get_total_event_count_ll(long long* out_count);
|
|
int db_get_event_count_since(time_t cutoff, long long* out_count);
|
|
int db_get_storage_size_bytes(long long* out_size);
|
|
cJSON* db_get_event_kind_distribution_rows(long long* out_total_events);
|
|
cJSON* db_get_top_pubkeys_rows(int limit);
|
|
cJSON* db_get_subscription_details_rows(void);
|
|
|
|
// Config helpers
|
|
cJSON* db_get_all_config_rows(void);
|
|
char* db_get_config_value_dup(const char* key);
|
|
int db_set_config_value_full(const char* key, const char* value, const char* data_type,
|
|
const char* description, const char* category, int requires_restart);
|
|
int db_update_config_value_only(const char* key, const char* value);
|
|
int db_upsert_config_value(const char* key, const char* value, const char* data_type);
|
|
int db_store_relay_private_key_hex(const char* relay_privkey_hex);
|
|
char* db_get_relay_private_key_hex_dup(void);
|
|
int db_store_config_event(const cJSON* event);
|
|
|
|
// Event storage/timestamp/retrieval helpers
|
|
int db_insert_event_with_json(const char* id, const char* pubkey, long long created_at,
|
|
int kind, const char* event_type, const char* content,
|
|
const char* sig, const char* tags_json, const char* event_json,
|
|
int* out_step_rc, int* out_extended_errcode);
|
|
int db_get_event_time_bounds(long long* out_min_created_at, long long* out_max_created_at);
|
|
int db_event_id_exists(const char* event_id, int* out_exists);
|
|
cJSON* db_retrieve_event_by_id(const char* event_id);
|
|
char* db_get_latest_event_pubkey_for_kind_dup(int kind);
|
|
|
|
// Config table helpers
|
|
int db_get_config_row_count(int* out_count);
|
|
|
|
// Event tag helpers
|
|
int db_store_event_tags_cjson(const char* event_id, const cJSON* tags);
|
|
int db_populate_event_tags_from_existing(void);
|
|
|
|
// Auth/WoT rule helpers
|
|
int db_add_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value);
|
|
int db_remove_auth_rule(const char* rule_type, const char* pattern_type, const char* pattern_value);
|
|
int db_delete_wot_whitelist_rules(void);
|
|
int db_count_wot_whitelist_rules(void);
|
|
|
|
// Schema/DDL helpers
|
|
int db_table_exists(const char* table_name, int* out_exists);
|
|
char* db_get_schema_version_dup(void);
|
|
int db_exec_sql(const char* sql);
|
|
int db_wal_checkpoint_passive(void);
|
|
int db_wal_checkpoint_truncate(void);
|
|
|
|
// Caching relay inbox helpers (PostgreSQL-only; SQLite path returns error/no-op).
|
|
// These back the c-relay-pg inbox poller that destructively dequeues events
|
|
// written into the caching_event_inbox table by the external caching app.
|
|
cJSON* db_caching_inbox_dequeue_batch(int batch_size, int* out_count);
|
|
int db_caching_inbox_pending_counts(int* out_live_count, int* out_backfill_count);
|
|
int db_caching_inbox_oldest_age(int* out_oldest_age_seconds);
|
|
|
|
// Backfill author progress from caching_service_state (per-author until-cursor
|
|
// drain model). Returns DB_OK and fills out_complete/out_total, or DB_ERROR.
|
|
int db_caching_backfill_author_counts(int* out_complete, int* out_total);
|
|
int db_caching_inbox_insert(const char* event_id, const char* event_json,
|
|
const char* source_relay, const char* source_class,
|
|
int priority);
|
|
|
|
// Profile metadata and outbox relay helpers.
|
|
// db_get_profile_metadata: [DEPRECATED] returns the most recent kind-0 metadata
|
|
// for a pubkey as a cJSON object with name/picture/about/nip05/display_name
|
|
// fields parsed from the event content JSON. Returns NULL if no kind-0 event
|
|
// exists. Caller must cJSON_Delete() the result.
|
|
// Prefer db_get_profile() which reads from the profiles cache table.
|
|
cJSON* db_get_profile_metadata(const char* pubkey);
|
|
// db_get_outbox_relays: returns relay URLs from the most recent kind-10002
|
|
// event for a pubkey, as a cJSON array of strings. Returns NULL if no
|
|
// kind-10002 event exists. Caller must cJSON_Delete() the result.
|
|
cJSON* db_get_outbox_relays(const char* pubkey);
|
|
|
|
// Profile cache (profiles table) lookups.
|
|
// db_get_profile: returns a single cached profile as a cJSON object with
|
|
// "pubkey", "name", "display_name", "best_name" (resolved per
|
|
// profile_name_preference config), and optional "picture"/"nip05"/etc.
|
|
// Returns NULL if no profile is cached. Caller must cJSON_Delete().
|
|
cJSON* db_get_profile(const char* pubkey);
|
|
// db_get_profiles: batch lookup for many pubkeys in one query. Returns a cJSON
|
|
// object keyed by pubkey hex -> profile object (same fields as db_get_profile).
|
|
// Pubkeys with no cached profile are absent from the result.
|
|
// Caller must cJSON_Delete(). Returns NULL on error.
|
|
cJSON* db_get_profiles(const char** pubkeys, int count);
|
|
|
|
#endif // DB_OPS_H
|