Skip to content

Commit f11cb37

Browse files
authored
Merge pull request #4409 from makr-code/copilot/create-training-folder
Add training materials from presentation and examples
2 parents fef77e4 + c6b365d commit f11cb37

39 files changed

Lines changed: 6493 additions & 133 deletions

include/api/themisdb_grpc_service.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ class RocksDBWrapper;
3131
class TransactionManager;
3232
} // namespace themis
3333

34+
// Interface forward declarations (always available without proto stubs)
35+
namespace themis {
36+
class IQueryEngine;
37+
class IVectorIndex;
38+
using IQueryEnginePtr = std::shared_ptr<IQueryEngine>;
39+
} // namespace themis
40+
3441
namespace themis {
3542
namespace api {
3643

@@ -45,7 +52,7 @@ namespace api {
4552
*
4653
* Lifecycle – register with GrpcApiServer before calling start():
4754
* @code
48-
* ThemisDBGrpcService svc(db, txn_mgr);
55+
* ThemisDBGrpcService svc(db, txn_mgr, aql_engine, vector_index);
4956
* grpc_api_server.registerService(svc.service()); // nullptr when stubs absent
5057
* grpc_api_server.start();
5158
* @endcode
@@ -56,10 +63,16 @@ namespace api {
5663
* - AQL : ExecuteAQL, StreamAQL (server-side streaming)
5764
* - Vector search : VectorSearch, FilteredVectorSearch, HybridSearch, FullTextSearch
5865
* - Health : HealthCheck
66+
*
67+
* When an AQL engine and/or vector index are provided via the extended
68+
* constructor the corresponding RPC stubs delegate to them rather than
69+
* returning UNIMPLEMENTED. See ThemisDBGrpcServiceFactory for a fluent
70+
* builder that wires all components together.
5971
*/
6072
class ThemisDBGrpcService {
6173
public:
6274
/**
75+
* @brief Construct with storage only (AQL and vector search return UNIMPLEMENTED).
6376
* @param db Storage backend (must outlive this object).
6477
* @param txn_mgr Transaction manager (must outlive this object).
6578
*/
@@ -68,6 +81,24 @@ class ThemisDBGrpcService {
6881
std::shared_ptr<TransactionManager> txn_mgr
6982
);
7083

84+
/**
85+
* @brief Construct with all components wired in.
86+
*
87+
* AQL engine enables ExecuteAQL, StreamAQL, HybridSearch, and FullTextSearch.
88+
* Vector index enables VectorSearch and FilteredVectorSearch.
89+
*
90+
* @param db Storage backend (must outlive this object).
91+
* @param txn_mgr Transaction manager (must outlive this object).
92+
* @param aql_engine Query engine for AQL RPCs (may be nullptr).
93+
* @param vector_index Vector similarity index (may be nullptr).
94+
*/
95+
ThemisDBGrpcService(
96+
std::shared_ptr<RocksDBWrapper> db,
97+
std::shared_ptr<TransactionManager> txn_mgr,
98+
std::shared_ptr<themis::IQueryEngine> aql_engine,
99+
std::shared_ptr<themis::IVectorIndex> vector_index
100+
);
101+
71102
~ThemisDBGrpcService();
72103

73104
/**
@@ -80,11 +111,16 @@ class ThemisDBGrpcService {
80111
void* service();
81112

82113
private:
83-
std::shared_ptr<RocksDBWrapper> db_;
84-
std::shared_ptr<TransactionManager> txn_mgr_;
114+
std::shared_ptr<RocksDBWrapper> db_;
115+
std::shared_ptr<TransactionManager> txn_mgr_;
116+
std::shared_ptr<themis::IQueryEngine> aql_engine_;
117+
std::shared_ptr<themis::IVectorIndex> vector_index_;
85118

86119
class Impl;
87120
std::unique_ptr<Impl> impl_;
121+
122+
/// Internal helper used by both constructors.
123+
void buildImpl();
88124
};
89125

90126
} // namespace api
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#pragma once
2+
3+
#include "api/themisdb_grpc_service.h"
4+
#include <memory>
5+
6+
// Forward declarations
7+
namespace themis {
8+
class RocksDBWrapper;
9+
class TransactionManager;
10+
class IQueryEngine;
11+
class IVectorIndex;
12+
} // namespace themis
13+
14+
namespace themis {
15+
namespace api {
16+
17+
/**
18+
* @brief Fluent factory for building a fully-wired ThemisDBGrpcService.
19+
*
20+
* Usage:
21+
* @code
22+
* auto svc = ThemisDBGrpcServiceFactory{}
23+
* .withDb(my_db)
24+
* .withTxnMgr(my_txn_mgr)
25+
* .withQueryEngine(my_aql_engine)
26+
* .withVectorIndex(my_vector_index)
27+
* .build();
28+
* grpc_server.registerService(svc->service());
29+
* @endcode
30+
*
31+
* All components are optional. When a component is not provided the
32+
* corresponding RPC stubs return grpc::StatusCode::UNIMPLEMENTED.
33+
*
34+
* This factory is the recommended way to assemble a ThemisDBGrpcService
35+
* because it makes the dependency set explicit and allows incremental wiring
36+
* as components become available.
37+
*/
38+
class ThemisDBGrpcServiceFactory {
39+
public:
40+
ThemisDBGrpcServiceFactory() = default;
41+
42+
/// Set the storage backend.
43+
ThemisDBGrpcServiceFactory& withDb(
44+
std::shared_ptr<RocksDBWrapper> db) {
45+
db_ = std::move(db);
46+
return *this;
47+
}
48+
49+
/// Set the transaction manager.
50+
ThemisDBGrpcServiceFactory& withTxnMgr(
51+
std::shared_ptr<TransactionManager> txn_mgr) {
52+
txn_mgr_ = std::move(txn_mgr);
53+
return *this;
54+
}
55+
56+
/// Set the AQL engine (enables ExecuteAQL, StreamAQL, HybridSearch, FullTextSearch).
57+
ThemisDBGrpcServiceFactory& withQueryEngine(
58+
std::shared_ptr<themis::IQueryEngine> engine) {
59+
aql_engine_ = std::move(engine);
60+
return *this;
61+
}
62+
63+
/// Set the vector index (enables VectorSearch and FilteredVectorSearch).
64+
ThemisDBGrpcServiceFactory& withVectorIndex(
65+
std::shared_ptr<themis::IVectorIndex> index) {
66+
vector_index_ = std::move(index);
67+
return *this;
68+
}
69+
70+
/// Build and return the configured ThemisDBGrpcService.
71+
std::unique_ptr<ThemisDBGrpcService> build() const {
72+
return std::make_unique<ThemisDBGrpcService>(
73+
db_,
74+
txn_mgr_,
75+
aql_engine_,
76+
vector_index_
77+
);
78+
}
79+
80+
private:
81+
std::shared_ptr<RocksDBWrapper> db_;
82+
std::shared_ptr<TransactionManager> txn_mgr_;
83+
std::shared_ptr<themis::IQueryEngine> aql_engine_;
84+
std::shared_ptr<themis::IVectorIndex> vector_index_;
85+
};
86+
87+
} // namespace api
88+
} // namespace themis

include/query/query_federation.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@
2323
#pragma once
2424

2525
#include "sharding/shard_router.h"
26+
#include "sharding/urn_resolver.h"
2627
#include "sharding/sharding_manager.h"
2728
#include "query/query_optimizer.h"
2829
#include <string>
2930
#include <vector>
3031
#include <memory>
32+
#include <optional>
33+
#include <atomic>
3134
#include <nlohmann/json.hpp>
3235

3336
namespace themis::query {
@@ -223,6 +226,18 @@ class QueryFederation {
223226
* @return Query metadata (tables, predicates, etc.)
224227
*/
225228
struct QueryMetadata {
229+
// ── Shard-key predicate ──────────────────────────────────────────────
230+
// Populated by analyzeQuery() when it detects a _key == <value> or
231+
// _key >= <min> AND _key <= <max> predicate, enabling partition pruning.
232+
struct ShardKeyPredicate {
233+
enum class Kind { POINT, RANGE };
234+
Kind kind;
235+
std::string collection;
236+
std::string key_value; // used when kind == POINT
237+
std::string key_min; // used when kind == RANGE
238+
std::string key_max; // used when kind == RANGE
239+
};
240+
226241
std::vector<std::string> tables;
227242
std::vector<std::string> predicates;
228243
std::vector<std::string> projections;
@@ -231,6 +246,9 @@ class QueryFederation {
231246
std::optional<std::string> order_by;
232247
std::optional<uint64_t> limit;
233248
std::optional<uint64_t> offset;
249+
250+
// Shard-key routing hint (nullopt → no routing hint, use scatter-gather)
251+
std::optional<ShardKeyPredicate> shard_key_predicate;
234252

235253
// Extended for adaptive capability-based routing
236254
std::string query_text; // Original query text

include/sharding/consistent_hash.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,28 @@ class ConsistentHashRing {
121121
* @return List of unique shard IDs
122122
*/
123123
std::vector<std::string> getAllShards() const;
124+
125+
/**
126+
* Get all shards responsible for any key whose hash lies in [hash_start, hash_end].
127+
*
128+
* Performs a clockwise ring walk from hash_start to hash_end, collecting every
129+
* distinct shard ID encountered. When hash_start > hash_end the range wraps
130+
* around the ring and all shards are returned.
131+
*
132+
* @param hash_start Lower bound of the hash range (inclusive)
133+
* @param hash_end Upper bound of the hash range (inclusive)
134+
* @return Ordered, deduplicated list of shard IDs (may be all shards)
135+
*/
136+
std::vector<std::string> getShardsInRange(uint64_t hash_start, uint64_t hash_end) const;
137+
138+
/**
139+
* Hash an arbitrary string key using the internal FNV-1a + mix function.
140+
* Exposed so callers can compute consistent hash positions without duplicating
141+
* the hash logic.
142+
* @param key String to hash
143+
* @return 64-bit hash value
144+
*/
145+
uint64_t hashKey(const std::string& key) const { return hash(key); }
124146

125147
/**
126148
* Calculate balance factor (standard deviation of virtual nodes per shard)

include/sharding/shard_router.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,30 @@ class ShardRouter {
159159
* @param query Query to execute
160160
* @return Merged results from all shards
161161
*/
162-
std::vector<ShardResult> scatterGather(const std::string& query);
162+
virtual std::vector<ShardResult> scatterGather(const std::string& query);
163+
164+
/**
165+
* Execute a query on a specific subset of shards.
166+
*
167+
* Behaves identically to scatterGather but only contacts the shards
168+
* whose IDs appear in @p shard_ids. Unknown or unhealthy shard IDs are
169+
* skipped with a WARN log rather than causing an error.
170+
*
171+
* @param query AQL query string
172+
* @param shard_ids Shard identifiers to target
173+
* @return Results from the targeted shards (success + failure entries)
174+
*/
175+
virtual std::vector<ShardResult> executeOnShards(
176+
const std::string& query,
177+
const std::vector<std::string>& shard_ids
178+
);
179+
180+
/**
181+
* Access the URN resolver to perform key-based shard lookups.
182+
* @return Reference to the resolver
183+
*/
184+
URNResolver& getResolver() { return *resolver_; }
185+
const URNResolver& getResolver() const { return *resolver_; }
163186

164187
/**
165188
* Execute cross-shard join (simplified two-phase approach)

include/sharding/urn_resolver.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,36 @@ class URNResolver {
8989
* @return Shard ID string, or empty if ring is empty
9090
*/
9191
std::string getShardId(const URN& urn) const;
92+
93+
/**
94+
* Get the single shard responsible for an arbitrary partition key.
95+
*
96+
* The key is hashed with the same FNV-1a + mix64 function used by the
97+
* ring, then looked up with a clockwise walk.
98+
*
99+
* @param collection Collection name (for logging / future topology hints)
100+
* @param key Partition key value (e.g. document _key)
101+
* @return Shard ID, or empty string if the ring is empty
102+
*/
103+
std::string getShardForKey(const std::string& collection, const std::string& key) const;
104+
105+
/**
106+
* Get all shards that could own keys in the range [min_key, max_key].
107+
*
108+
* Hashes both endpoints and collects every shard whose virtual-node
109+
* token falls within that hash range (clockwise walk). For wrap-around
110+
* ranges every shard is returned.
111+
*
112+
* @param collection Collection name
113+
* @param min_key Inclusive lower bound of the key range
114+
* @param max_key Inclusive upper bound of the key range
115+
* @return Deduplicated list of shard IDs; never empty if the ring is not empty
116+
*/
117+
std::vector<std::string> getShardsForKeyRange(
118+
const std::string& collection,
119+
const std::string& min_key,
120+
const std::string& max_key
121+
) const;
92122

93123
/**
94124
* Get all Shards in cluster

0 commit comments

Comments
 (0)