Skip to content

Commit 3ba0f9b

Browse files
authored
Feat/support event db mgr (#578)
* feat: add doc store * feat: add index * test: add index test case * fix: update the error report * feat: upgrade version * fix: revert the key and case * feat: add delete event db * fix: revert evm key
1 parent df52e86 commit 3ba0f9b

File tree

10 files changed

+332
-23
lines changed

10 files changed

+332
-23
lines changed

docker/start_localnet.sh

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@
33
echo "ADMIN ADDR ${ADMIN_ADDR}"
44
mkdir -p ./mutation_db ./state_db ./doc_db ./keys ./index_meta_db ./index_doc_db
55
echo "start store node..."
6-
/usr/bin/db3 store --admin-addr=${ADMIN_ADDR} --public-host 0.0.0.0 --rollup-interval 30000 --contract-addr=0xb9709ce5e749b80978182db1bedfb8c7340039a9 --evm-node-url=https://polygon-mumbai.g.alchemy.com/v2/kiuid-hlfzpnletzqdvwo38iqn0giefr > store.log 2>&1 &
6+
/usr/bin/db3 rollup --admin-addr=${ADMIN_ADDR} --bind-host 0.0.0.0 > rollup.log 2>&1 &
77
sleep 3
88
echo "start index node..."
9-
/usr/bin/db3 indexer --admin-addr=${ADMIN_ADDR} --public-host 0.0.0.0 --contract-addr=0xb9709ce5e749b80978182db1bedfb8c7340039a9 --evm-node-url=https://polygon-mumbai.g.alchemy.com/v2/kiuid-hlfzpnletzqdvwo38iqn0giefr> indexer.log 2>&1 &
9+
/usr/bin/db3 index --admin-addr=${ADMIN_ADDR} --bind-host 0.0.0.0 > index.log 2>&1 &
1010
sleep 3
11-
1211
npx serve -l 26629 -s /pages > pages.log 2>&1 &
1312

14-
AR_ADDRESS=`cat /store.log | grep filestore | awk '{print $NF}'`
13+
AR_ADDRESS=`less rollup.log | grep Arweave | awk '{print $NF}'`
14+
STORE_EVM_ADDRESS=`less rollup.log | grep Evm | grep address | awk '{print $NF}'`
1515
echo "the ar account address ${AR_ADDRESS}"
1616
echo "start ar testnet ..."
1717
bash /usr/bin/ar_miner.sh > miner.log 2>&1 &
1818
sleep 2
1919
curl http://127.0.0.1:1984/mint/${AR_ADDRESS}/10000000000000
2020
echo "Start the local db3 nodes successfully"
21-
echo "The storage node url: http://127.0.0.1:26619"
21+
echo "The rollup node url: http://127.0.0.1:26619"
2222
echo "The index node url: http://127.0.0.1:26639"
23-
echo "The console node url: http://127.0.0.1:26629/console"
24-
echo "The setup url: http://127.0.0.1:26629/welcome"
23+
echo "The setup url: http://127.0.0.1:26629"
2524
while true; do sleep 10 ; done

sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "db3.js",
3-
"version": "0.4.0",
3+
"version": "0.4.1",
44
"description": "DB3 Network Javascript API",
55
"author": "dbpunk labs",
66
"keywords": [

sdk/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ export {
5555
showDatabase,
5656
createCollection,
5757
showCollection,
58+
showCollectionFromIndex,
5859
getDatabase,
5960
getCollection,
6061
addIndex,
62+
deleteEventDatabase
6163
} from './store/database_v2'
6264

6365
export { Index, IndexType } from './proto/db3_database_v2'

sdk/src/provider/indexer_provider.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { SystemClient } from '../proto/db3_system.client'
2424
import {
2525
RunQueryRequest,
2626
GetContractSyncStatusRequest,
27+
GetCollectionOfDatabaseRequest,
2728
} from '../proto/db3_indexer'
2829
import { SetupRequest, GetSystemStatusRequest } from '../proto/db3_system'
2930
import { Query } from '../proto/db3_database_v2'
@@ -84,7 +85,6 @@ export class IndexerProvider {
8485
}
8586
async getContractSyncStatus() {
8687
const request: GetContractSyncStatusRequest = {}
87-
8888
try {
8989
const { response } = await this.client.getContractSyncStatus(
9090
request
@@ -94,4 +94,18 @@ export class IndexerProvider {
9494
throw new DB3Error(e as RpcError)
9595
}
9696
}
97+
98+
async getCollectionOfDatabase(db: string) {
99+
const request: GetCollectionOfDatabaseRequest = {
100+
dbAddr: db,
101+
}
102+
try {
103+
const { response } = await this.client.getCollectionOfDatabase(
104+
request
105+
)
106+
return response
107+
} catch (e) {
108+
throw new DB3Error(e)
109+
}
110+
}
97111
}

sdk/src/store/database_v2.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,58 @@ import {
3333
DocumentDatabaseMutation,
3434
EventDatabaseMutation,
3535
AddIndexMutation,
36+
DeleteEventDatabaseMutation,
3637
} from '../proto/db3_mutation_v2'
3738

3839
import { Client, ReadClient } from '../client/types'
3940
import { toHEX, fromHEX } from '../crypto/crypto_utils'
4041
import { Index } from '../proto/db3_database_v2'
4142

43+
/**
44+
*
45+
* Delete the event database
46+
*
47+
* ```ts
48+
* const result = await deleteEventDatabase(client,
49+
* "0x....")
50+
* ```
51+
* @param client - the client instance
52+
* @param address - the address of event database
53+
* @returns the {@link MutationResult}
54+
* @note only the owner of event database can delete the event database
55+
*
56+
**/
57+
export async function deleteEventDatabase(client: Client, dbAddress: string) {
58+
const mutation: DeleteEventDatabaseMutation = {}
59+
const body: Mutation_BodyWrapper = {
60+
body: {
61+
oneofKind: 'deleteEventDatabaseMutation',
62+
deleteEventDatabaseMutation: mutation,
63+
},
64+
dbAddress: fromHEX(dbAddress),
65+
}
66+
67+
const dm: Mutation = {
68+
action: MutationAction.DeleteEventDB,
69+
bodies: [body],
70+
}
71+
const payload = Mutation.toBinary(dm)
72+
const response = await client.provider.sendMutation(
73+
payload,
74+
client.nonce.toString()
75+
)
76+
if (response.code == 0) {
77+
client.nonce += 1
78+
return {
79+
id: response.id,
80+
block: response.block,
81+
order: response.order,
82+
} as MutationResult
83+
} else {
84+
throw new Error('fail to create database')
85+
}
86+
}
87+
4288
/**
4389
*
4490
* Create an event database to store contract events
@@ -424,3 +470,29 @@ export async function showCollection(db: Database) {
424470
})
425471
return collectionList
426472
}
473+
474+
/**
475+
*
476+
* Query collections in the database from the index
477+
*
478+
* ```ts
479+
* const collections = await showCollectionFromIndex(db)
480+
* ```
481+
*
482+
* @param db - the instance of database
483+
* @returns the {@link Collection[]}
484+
*
485+
**/
486+
export async function showCollectionFromIndex(db: Database) {
487+
const response = await db.client.indexer.getCollectionOfDatabase(db.addr)
488+
const collectionList = response.collections.map((c, index) => {
489+
return {
490+
name: c.name,
491+
db,
492+
indexFields: c.indexFields,
493+
internal: c,
494+
state: response.states[index],
495+
} as Collection
496+
})
497+
return collectionList
498+
}

src/error/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,14 @@ pub enum DB3Error {
139139
DatabaseNotFound(String),
140140
#[error("database with addr {0} already exist")]
141141
DatabaseAlreadyExist(String),
142+
#[error("You have no permission to delete the database")]
143+
DatabasePermissionDenied(),
142144
#[error("collection with name {0} was not found in db {1}")]
143145
CollectionNotFound(String, String),
144146
#[error("collection {0} already exist in db {1}")]
145147
CollectionAlreadyExist(String, String),
146148
#[error("You have no permission to modify the collection")]
147-
CollectionPermssionDenied(),
149+
CollectionPermissionDenied(),
148150
}
149151

150152
pub type Result<T> = std::result::Result<T, DB3Error>;

src/node/src/indexer_impl.rs

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use db3_event::event_processor::EventProcessor;
2222
use db3_event::event_processor::EventProcessorConfig;
2323
use db3_proto::db3_indexer_proto::indexer_node_server::IndexerNode;
2424
use db3_proto::db3_indexer_proto::{
25-
ContractSyncStatus, GetContractSyncStatusRequest, GetContractSyncStatusResponse,
26-
RunQueryRequest, RunQueryResponse,
25+
ContractSyncStatus, GetCollectionOfDatabaseRequest, GetCollectionOfDatabaseResponse,
26+
GetContractSyncStatusRequest, GetContractSyncStatusResponse, RunQueryRequest, RunQueryResponse,
2727
};
2828
use db3_proto::db3_mutation_v2_proto::MutationAction;
2929
use db3_proto::db3_storage_proto::block_response::MutationWrapper;
@@ -201,9 +201,10 @@ impl IndexerNodeImpl {
201201
contract_address: &str,
202202
start_block: u64,
203203
) -> Result<()> {
204+
let db_addr = db.to_hex();
204205
let config = EventProcessorConfig {
205206
evm_node_url: evm_node_url.to_string(),
206-
db_addr: db.to_hex(),
207+
db_addr: db_addr.to_string(),
207208
abi: abi.to_string(),
208209
target_events: tables.iter().map(|t| t.to_string()).collect(),
209210
contract_addr: contract_address.to_string(),
@@ -217,14 +218,10 @@ impl IndexerNodeImpl {
217218
match self.processor_mapping.lock() {
218219
Ok(mut mapping) => {
219220
//TODO limit the total count
220-
if mapping.contains_key(contract_address) {
221-
warn!("contract addr {} exist", contract_address);
222-
return Err(DB3Error::WriteStoreError(format!(
223-
"contract_addr {} exist",
224-
contract_address
225-
)));
221+
if mapping.contains_key(db_addr.as_str()) {
222+
return Err(DB3Error::DatabaseAlreadyExist(db_addr.to_string()));
226223
}
227-
mapping.insert(contract_address.to_string(), processor.clone());
224+
mapping.insert(db_addr.to_string(), processor.clone());
228225
}
229226
_ => todo!(),
230227
}
@@ -241,6 +238,22 @@ impl IndexerNodeImpl {
241238
Ok(())
242239
}
243240

241+
fn close_event_task(&self, db: &DB3Address) -> Result<()> {
242+
let addr = db.to_hex();
243+
match self.processor_mapping.lock() {
244+
Ok(mut mapping) => match mapping.remove(addr.as_str()) {
245+
Some(task) => {
246+
task.close();
247+
}
248+
None => {
249+
return Err(DB3Error::DatabaseNotFound(addr.to_string()));
250+
}
251+
},
252+
_ => todo!(),
253+
}
254+
Ok(())
255+
}
256+
244257
async fn parse_and_apply_mutations(&self, mutations: &Vec<MutationWrapper>) -> Result<()> {
245258
for mutation in mutations.iter() {
246259
let header = mutation.header.as_ref().unwrap();
@@ -252,14 +265,16 @@ impl IndexerNodeImpl {
252265
let action = MutationAction::from_i32(dm.action).ok_or(DB3Error::WriteStoreError(
253266
"fail to convert action type".to_string(),
254267
))?;
268+
255269
let (block, order, doc_ids_map_str) = match &mutation.header {
256270
Some(header) => Ok((header.block_id, header.order_id, &header.doc_ids_map)),
257271
_ => Err(DB3Error::WriteStoreError(
258272
"invalid mutation header".to_string(),
259273
)),
260274
}?;
275+
261276
let doc_ids_map = MutationUtil::convert_doc_ids_map_to_vec(doc_ids_map_str)?;
262-
self.db_store.apply_mutation(
277+
let extra_items = self.db_store.apply_mutation(
263278
action,
264279
dm,
265280
&address,
@@ -269,6 +284,39 @@ impl IndexerNodeImpl {
269284
order,
270285
&doc_ids_map,
271286
)?;
287+
match action {
288+
MutationAction::CreateEventDb => {
289+
if extra_items.len() > 0 && extra_items[0].key.as_str() == "db_addr" {
290+
let addr = DB3Address::from_hex(extra_items[0].value.as_str())?;
291+
let (collections, _) = self.db_store.get_collection_of_database(&addr)?;
292+
let tables = collections.iter().map(|c| c.name.to_string()).collect();
293+
if let Some(database) = self.db_store.get_event_db(&addr)? {
294+
if let Err(e) = self
295+
.start_an_event_task(
296+
&addr,
297+
database.evm_node_url.as_str(),
298+
database.events_json_abi.as_str(),
299+
&tables,
300+
database.contract_address.as_str(),
301+
0,
302+
)
303+
.await
304+
{
305+
info!("start the event db {} with error {e}", addr.to_hex());
306+
} else {
307+
info!("start event db {} done", addr.to_hex());
308+
}
309+
}
310+
}
311+
}
312+
MutationAction::DeleteEventDb => {
313+
if extra_items.len() > 0 && extra_items[0].key.as_str() == "db_addr" {
314+
let addr = DB3Address::from_hex(extra_items[0].value.as_str())?;
315+
self.close_event_task(&addr)?;
316+
}
317+
}
318+
_ => {}
319+
}
272320
}
273321
Ok(())
274322
}
@@ -295,6 +343,29 @@ impl IndexerNode for IndexerNodeImpl {
295343
Ok(Response::new(GetContractSyncStatusResponse { status_list }))
296344
}
297345

346+
async fn get_collection_of_database(
347+
&self,
348+
request: Request<GetCollectionOfDatabaseRequest>,
349+
) -> std::result::Result<Response<GetCollectionOfDatabaseResponse>, Status> {
350+
let r = request.into_inner();
351+
let addr = DB3Address::from_hex(r.db_addr.as_str())
352+
.map_err(|e| Status::invalid_argument(format!("invalid database address {e}")))?;
353+
let (collections, collection_states) = self
354+
.db_store
355+
.get_collection_of_database(&addr)
356+
.map_err(|e| Status::internal(format!("fail to get collect of database {e}")))?;
357+
358+
info!(
359+
"query collection count {} with database {}",
360+
collections.len(),
361+
r.db_addr.as_str()
362+
);
363+
Ok(Response::new(GetCollectionOfDatabaseResponse {
364+
collections,
365+
states: collection_states,
366+
}))
367+
}
368+
298369
async fn run_query(
299370
&self,
300371
request: Request<RunQueryRequest>,

src/proto/proto/db3_indexer.proto

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,23 @@ message ContractSyncStatus {
4747
uint64 event_number = 4;
4848
}
4949

50+
message GetCollectionOfDatabaseResponse {
51+
repeated db3_database_v2_proto.Collection collections = 1;
52+
repeated db3_database_v2_proto.CollectionState states = 2;
53+
}
54+
message GetCollectionOfDatabaseRequest {
55+
string db_addr = 1;
56+
}
57+
5058
message GetContractSyncStatusResponse {
5159
repeated ContractSyncStatus status_list = 1;
5260
}
61+
5362
message GetContractSyncStatusRequest {}
5463

5564
service IndexerNode {
5665
rpc GetContractSyncStatus(GetContractSyncStatusRequest) returns (GetContractSyncStatusResponse) {}
66+
rpc GetCollectionOfDatabase(GetCollectionOfDatabaseRequest) returns (GetCollectionOfDatabaseResponse) {}
5767
// method for query document
5868
rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) {}
5969
}

src/proto/proto/db3_mutation_v2.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ message MintDocumentDatabaseMutation {
4747
string sender = 6;
4848
}
4949

50+
message DeleteEventDatabaseMutation {}
51+
5052
message AddIndexMutation {
5153
string collection_name = 1;
5254
repeated db3_database_v2_proto.Index index_fields = 2;
@@ -108,6 +110,7 @@ enum MutationAction {
108110
MintDocumentDB = 6;
109111
MintCollection = 7;
110112
AddIndex = 8;
113+
DeleteEventDB = 9;
111114
}
112115

113116
enum MutationRollupStatus {
@@ -128,6 +131,7 @@ message Mutation {
128131
MintDocumentDatabaseMutation mint_doc_database_mutation = 6;
129132
MintCollectionMutation mint_collection_mutation = 7;
130133
AddIndexMutation add_index_mutation = 8;
134+
DeleteEventDatabaseMutation delete_event_database_mutation = 9;
131135
}
132136
}
133137
repeated BodyWrapper bodies = 3;

0 commit comments

Comments
 (0)