Skip to content

Commit 02629f8

Browse files
authored
Merge branch 'master' into fix-raw-scan-limit
2 parents 10b6f44 + caa869e commit 02629f8

File tree

5 files changed

+108
-20
lines changed

5 files changed

+108
-20
lines changed

README.md

Lines changed: 92 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,123 @@
88
This crate provides a clean, ready to use client for [TiKV](https://github.com/tikv/tikv), a
99
distributed transactional Key-Value database written in Rust.
1010

11-
With this crate you can easily connect to any TiKV deployment, interact with it, and mutate the data it contains.
11+
With this crate you can easily connect to any TiKV deployment, interact with it, and mutate the data it contains. It uses async/await internally and exposes some `async fn` APIs as well.
1212

1313
This is an open source (Apache 2) project hosted by the Cloud Native Computing Foundation (CNCF) and maintained by the TiKV Authors. *We'd love it if you joined us in improving this project.*
1414

15-
## Using the client
15+
## Getting started
1616

17-
The TiKV client is a Rust library (crate). It uses async/await internally and exposes some `async fn` APIs as well.
18-
19-
To use this crate in your project, add it as a dependency in your `Cargo.toml`:
17+
The TiKV client is a Rust library (crate). To use this crate in your project, add following dependencies in your `Cargo.toml`:
2018

2119
```toml
2220
[dependencies]
23-
# ...Your other dependencies...
2421
tikv-client = { git = "https://github.com/tikv/client-rust.git" }
22+
23+
[patch.crates-io]
24+
raft-proto = { git = "https://github.com/tikv/raft-rs", rev = "e624c1d48460940a40d8aa69b5329460d9af87dd" }
2525
```
2626

2727
The client requires a Git dependency until we can [publish it](https://github.com/tikv/client-rust/issues/32).
2828

29-
There are [examples](examples) which show how to use the client in a Rust program.
29+
The client provides two modes to interact with TiKV: raw and transactional.
30+
In the current version (0.0.0), the transactional API only supports optimistic transactions.
31+
32+
Important note: It is **not recommended or supported** to use both the raw and transactional APIs on the same database.
33+
34+
### Code examples
35+
36+
Raw mode:
37+
38+
```rust
39+
let config = Config::new(vec!["127.0.0.1:2379"]);
40+
let client = RawClient::new(config).await?;
41+
client.put("key".to_owned(), "value".to_owned()).await;
42+
let value = client.get("key".to_owned()).await;
43+
```
44+
45+
Transactional mode:
46+
47+
```rust
48+
let config = Config::new(vec!["127.0.0.1:2379"]);
49+
let txn_client = TransactionClient::new(config).await?;
50+
let mut txn = txn_client.begin().await?;
51+
txn.put("key".to_owned(), "value".to_owned()).await?;
52+
let value = txn.get("key".to_owned()).await;
53+
txn.commit().await?;
54+
```
55+
56+
There are some [examples](examples) which show how to use the client in a Rust program.
57+
58+
### API
59+
60+
#### Raw requests
61+
62+
| Request | Main parameter type | Successful result type | Noteworthy Behavior |
63+
| -------------- | ------------------- | ---------------------- | --------------------------------------------- |
64+
| `put` | `KvPair` | `()` | |
65+
| `get` | `Key` | `Option<Value>` | |
66+
| `delete` | `Key` | `()` | |
67+
| `scan` | `BoundRange` | `Vec<KvPair>` | |
68+
| `batch_put` | `Iter<KvPair>` | `()` | |
69+
| `batch_get` | `Iter<Key>` | `Vec<KvPair>` | Skip non-existent keys; Does not retain order |
70+
| `batch_delete` | `Iter<Key>` | `()` | |
71+
| `delete_range` | `BoundRange` | `()` | |
72+
73+
#### Transactional requests
74+
75+
| Request | Main parameter type | Successful result type | Noteworthy Behavior |
76+
| ----------- | ------------------- | ---------------------- | --------------------------------------------- |
77+
| `put` | `KvPair` | `()` | |
78+
| `get` | `Key` | `Option<value>` | |
79+
| `delete` | `Key` | `()` | |
80+
| `scan` | `BoundRange` | `Iter<KvPair>` | |
81+
| `batch_get` | `Iter<Key>` | `Iter<KvPair>` | Skip non-existent keys; Does not retain order |
82+
| `lock_keys` | `KvPair` | `()` | |
83+
84+
For detailed behavior of each request, please refer to the [doc](#Access-the-documentation).
85+
86+
#### Experimental raw requests
87+
88+
You must be careful if you want to use the following request(s). Read the description for reasons.
89+
90+
| Request | Main parameter type | Successful result type |
91+
| -------------- | ------------------- | ---------------------- |
92+
| `batch_scan` | `Iter<BoundRange>` | `Vec<KvPair>` |
93+
94+
The `each_limit` parameter does not work as expected. It does not limit the number of results returned of each range, instead it limits the number of results in each region of each range. As a result, you may get **more than** `each_limit` key-value pairs for each range. But you should not miss any entries.
95+
96+
The results of `batch_scan` are flattened. The order of ranges is retained.
97+
98+
### Useful types
99+
100+
To use the client, there are 4 types you will need.
101+
102+
`Key` is simply a vector of bytes(`Vec<u8>`). `String` and `Vec<u8>` implements `Into<Key>`, so you can directly pass them to clients.
103+
104+
`Value` is just an alias of `Vec<u8>`.
105+
106+
`KvPair` is a tuple consisting of a `Key` and a `Value`. It also provides some convenience methods for conversion to and from other types.
107+
108+
`BoundRange` is used for range related requests like `scan`. It implements `From` for usual ranges so you can just create a range and pass them to the request.For instance, `client.scan("k2".to_owned()..="k5".to_owned(), 5)` or `client.delete_range(vec![]..)`.
30109

31110
## Access the documentation
32111

33112
We recommend using the cargo-generated documentation to browse and understand the API. We've done
34113
our best to include ample, tested, and understandable examples.
35114

36-
You can visit [docs.rs/tikv-client](https://docs.rs/tikv-client/), or build the documentation yourself.
37-
38115
You can access the documentation on your machine by running the following in any project that depends on `tikv-client`.
39116

40117
```bash
41118
cargo doc --package tikv-client --open
42119
# If it didn't work, browse file URL it tried to open with your browser.
43120
```
44121

45-
## Minimal Rust Version
122+
## Known issues
123+
124+
If you use transactional APIs, you'll need to perform GC in TiKV to save storage.
125+
However, current implementation does not provide a direct way to do this. A workaround is described in [#180](https://github.com/tikv/client-rust/issues/180).
126+
127+
## Minimal Rust version
46128

47129
This crate supports Rust 1.40 and above.
48130

examples/raw.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,7 @@ async fn main() -> Result<()> {
9494
let keys: Vec<_> = pairs.into_iter().map(|p| p.key().clone()).collect();
9595
assert_eq!(
9696
&keys,
97-
&[
98-
Key::from("k1".to_owned()),
99-
Key::from("k2".to_owned()),
100-
Key::from("k3".to_owned())
101-
]
97+
&[Key::from("k1".to_owned()), Key::from("k2".to_owned()),]
10298
);
10399
println!("Scaning from {:?} to {:?} gives: {:?}", start, end, keys);
104100

src/raw/client.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ impl Client {
103103
/// Create a new 'batch get' request.
104104
///
105105
/// Once resolved this request will result in the fetching of the values associated with the
106-
/// given keys.
106+
/// given keys
107107
/// Non-existent entries will be skipped. The order of the keys is not retained.
108108
///
109109
/// ```rust,no_run
@@ -174,6 +174,7 @@ impl Client {
174174
/// Create a new 'delete' request.
175175
///
176176
/// Once resolved this request will result in the deletion of the given key.
177+
/// It does not return an error if the key does not exist.
177178
///
178179
/// ```rust,no_run
179180
/// # use tikv_client::{Key, Config, RawClient};
@@ -194,6 +195,7 @@ impl Client {
194195
/// Create a new 'batch delete' request.
195196
///
196197
/// Once resolved this request will result in the deletion of the given keys.
198+
/// It does not return an error if some of the keys do not exist and will delete the others.
197199
///
198200
/// ```rust,no_run
199201
/// # use tikv_client::{Config, RawClient};

src/raw/requests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,9 @@ impl KvRequest for kvrpcpb::RawDeleteRangeRequest {
333333
fn reduce(
334334
results: BoxStream<'static, Result<Self::Result>>,
335335
) -> BoxFuture<'static, Result<Self::Result>> {
336-
results.try_for_each(|_| future::ready(Ok(()))).boxed()
336+
results
337+
.try_for_each_concurrent(None, |_| future::ready(Ok(())))
338+
.boxed()
337339
}
338340
}
339341

src/transaction/requests.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,9 @@ impl KvRequest for kvrpcpb::PrewriteRequest {
348348
fn reduce(
349349
results: BoxStream<'static, Result<Self::Result>>,
350350
) -> BoxFuture<'static, Result<Self::Result>> {
351-
results.try_for_each(|_| future::ready(Ok(()))).boxed()
351+
results
352+
.try_for_each_concurrent(None, |_| future::ready(Ok(())))
353+
.boxed()
352354
}
353355
}
354356

@@ -408,7 +410,9 @@ impl KvRequest for kvrpcpb::CommitRequest {
408410
fn reduce(
409411
results: BoxStream<'static, Result<Self::Result>>,
410412
) -> BoxFuture<'static, Result<Self::Result>> {
411-
results.try_for_each(|_| future::ready(Ok(()))).boxed()
413+
results
414+
.try_for_each_concurrent(None, |_| future::ready(Ok(())))
415+
.boxed()
412416
}
413417
}
414418

@@ -454,7 +458,9 @@ impl KvRequest for kvrpcpb::BatchRollbackRequest {
454458
fn reduce(
455459
results: BoxStream<'static, Result<Self::Result>>,
456460
) -> BoxFuture<'static, Result<Self::Result>> {
457-
results.try_for_each(|_| future::ready(Ok(()))).boxed()
461+
results
462+
.try_for_each_concurrent(None, |_| future::ready(Ok(())))
463+
.boxed()
458464
}
459465
}
460466

0 commit comments

Comments
 (0)