1use super::tt_wrapper::{Client, ClientConfig, IteratorType};
2use v_individual_model::onto::individual::Individual;
3use v_individual_model::onto::parser::parse_raw;
4use crate::common::{Storage, StorageId, StorageResult};
5use crate::RuntimeWrapper;
6use std::str;
7
8pub struct TTStorage {
9 rt: RuntimeWrapper,
10 client: Client,
11}
12
13const INDIVIDUALS_SPACE_ID: i32 = 512;
14const TICKETS_SPACE_ID: i32 = 513;
15const AZ_SPACE_ID: i32 = 514;
16
17impl TTStorage {
18 pub fn new(tt_uri: String, login: &str, pass: &str) -> TTStorage {
19 TTStorage {
20 rt: RuntimeWrapper::new(),
21 client: ClientConfig::new(tt_uri, login, pass).set_timeout_time_ms(1000).set_reconnect_time_ms(10000).build(),
22 }
23 }
24}
25
26impl Storage for TTStorage {
27 fn get_individual(&mut self, storage: StorageId, uri: &str, iraw: &mut Individual) -> StorageResult<()> {
28 let space = if storage == StorageId::Tickets {
29 TICKETS_SPACE_ID
30 } else if storage == StorageId::Az {
31 AZ_SPACE_ID
32 } else {
33 INDIVIDUALS_SPACE_ID
34 };
35
36 let key = (uri,);
37
38 match self.rt.block_on(self.client.select(space, 0, &key, 0, 100, IteratorType::EQ)) {
39 Ok(v) => {
40 if !v.data.is_empty() {
41 iraw.set_raw(&v.data[5..]);
42 if parse_raw(iraw).is_ok() {
43 return StorageResult::Ok(());
44 } else {
45 return StorageResult::UnprocessableEntity;
46 }
47 }
48 StorageResult::NotFound
49 },
50 Err(_) => StorageResult::UnprocessableEntity,
51 }
52 }
53
54 fn get_value(&mut self, storage: StorageId, key: &str) -> StorageResult<String> {
55 let space = if storage == StorageId::Tickets {
56 TICKETS_SPACE_ID
57 } else if storage == StorageId::Az {
58 AZ_SPACE_ID
59 } else {
60 INDIVIDUALS_SPACE_ID
61 };
62
63 let key_tuple = (key,);
64
65 match self.rt.block_on(self.client.select(space, 0, &key_tuple, 0, 100, IteratorType::EQ)) {
66 Ok(v) => {
67 match std::str::from_utf8(&v.data[5..]) {
68 Ok(s) => StorageResult::Ok(s.to_string()),
69 Err(_) => StorageResult::Error("Invalid UTF-8 data".to_string()),
70 }
71 },
72 Err(e) => {
73 error!("TTStorage: fail get [{}] from tarantool, err={:?}", key, e);
74 StorageResult::NotFound
75 },
76 }
77 }
78
79 fn get_raw_value(&mut self, storage: StorageId, key: &str) -> StorageResult<Vec<u8>> {
80 let space = if storage == StorageId::Tickets {
81 TICKETS_SPACE_ID
82 } else if storage == StorageId::Az {
83 AZ_SPACE_ID
84 } else {
85 INDIVIDUALS_SPACE_ID
86 };
87
88 let key_tuple = (key,);
89
90 match self.rt.block_on(self.client.select(space, 0, &key_tuple, 0, 100, IteratorType::EQ)) {
91 Ok(v) => StorageResult::Ok(v.data[5..].to_vec()),
92 Err(e) => {
93 error!("TTStorage: fail get raw [{}] from tarantool, err={:?}", key, e);
94 StorageResult::NotFound
95 },
96 }
97 }
98
99 fn put_value(&mut self, storage: StorageId, key: &str, val: &str) -> StorageResult<()> {
100 let space = if storage == StorageId::Tickets {
101 TICKETS_SPACE_ID
102 } else if storage == StorageId::Az {
103 AZ_SPACE_ID
104 } else {
105 INDIVIDUALS_SPACE_ID
106 };
107
108 let tuple = (key, val);
109
110 match self.rt.block_on(self.client.replace(space, &tuple)) {
111 Ok(_) => StorageResult::Ok(()),
112 Err(e) => {
113 error!("tarantool: fail replace, db [{:?}], err = {:?}", storage, e);
114 StorageResult::Error(format!("Failed to put value: {:?}", e))
115 },
116 }
117 }
118
119 fn put_raw_value(&mut self, storage: StorageId, _key: &str, val: Vec<u8>) -> StorageResult<()> {
120 let space = if storage == StorageId::Tickets {
121 TICKETS_SPACE_ID
122 } else if storage == StorageId::Az {
123 AZ_SPACE_ID
124 } else {
125 INDIVIDUALS_SPACE_ID
126 };
127
128 match self.rt.block_on(self.client.replace_raw(space, val)) {
129 Ok(_) => StorageResult::Ok(()),
130 Err(e) => {
131 error!("tarantool: fail replace raw, db [{:?}], err = {:?}", storage, e);
132 StorageResult::Error(format!("Failed to put raw value: {:?}", e))
133 },
134 }
135 }
136
137 fn remove_value(&mut self, storage: StorageId, key: &str) -> StorageResult<()> {
138 let space = if storage == StorageId::Tickets {
139 TICKETS_SPACE_ID
140 } else if storage == StorageId::Az {
141 AZ_SPACE_ID
142 } else {
143 INDIVIDUALS_SPACE_ID
144 };
145
146 let tuple = (key,);
147
148 match self.rt.block_on(self.client.delete(space, &tuple)) {
149 Ok(_) => StorageResult::Ok(()),
150 Err(e) => {
151 error!("tarantool: fail remove, db [{:?}], err = {:?}", storage, e);
152 StorageResult::NotFound
153 },
154 }
155 }
156
157 fn count(&mut self, storage: StorageId) -> StorageResult<usize> {
158 let space_name = if storage == StorageId::Tickets {
159 "TICKETS"
160 } else if storage == StorageId::Az {
161 "AZ"
162 } else {
163 "INDIVIDUALS"
164 };
165
166 match self.rt.block_on(self.client.eval(format!("return box.space.{}:len()", space_name), &(0,))) {
167 Ok(response) => {
168 match response.decode::<(u64,)>() {
169 Ok(res) => StorageResult::Ok(res.0 as usize),
170 Err(e) => {
171 error!("failed to decode count response: db [{}], err = {:?}", space_name, e);
172 StorageResult::Error("Failed to decode count response".to_string())
173 },
174 }
175 },
176 Err(e) => {
177 error!("failed to count the number of records: db [{}], err = {:?}", space_name, e);
178 StorageResult::Error(format!("Failed to count records: {:?}", e))
179 },
180 }
181 }
182}