tosnativeclient 1.0.5__tar.gz → 1.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tosnativeclient might be problematic. Click here for more details.

@@ -1521,7 +1521,7 @@ dependencies = [
1521
1521
 
1522
1522
  [[package]]
1523
1523
  name = "tosnativeclient"
1524
- version = "1.0.5"
1524
+ version = "1.0.7"
1525
1525
  dependencies = [
1526
1526
  "arc-swap",
1527
1527
  "async-channel",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "tosnativeclient"
3
- version = "1.0.5"
3
+ version = "1.0.7"
4
4
  edition = "2021"
5
5
  publish = false
6
6
  authors = ["xiangshijian"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tosnativeclient
3
- Version: 1.0.5
3
+ Version: 1.0.7
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -3,16 +3,18 @@ use crate::tos_error::{map_error_from_string, map_tos_error};
3
3
  use crate::tos_model::ListObjectsResult;
4
4
  use arc_swap::ArcSwap;
5
5
  use async_channel::Receiver;
6
+ use futures_util::AsyncWriteExt;
6
7
  use pyo3::types::PyTuple;
7
8
  use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyRefMut, PyResult, Python};
8
9
  use std::sync::atomic::{AtomicI8, Ordering};
9
10
  use std::sync::{Arc, RwLock};
10
11
  use tokio::runtime::Runtime;
12
+ use tokio::task::JoinHandle;
11
13
  use ve_tos_rust_sdk::asynchronous::object::ObjectAPI;
12
14
  use ve_tos_rust_sdk::error::TosError;
13
15
  use ve_tos_rust_sdk::object::{ListObjectsType2Input, ListObjectsType2Output};
14
16
 
15
- const DEFAULT_TASK_COUNT: usize = 5;
17
+ const DEFAULT_TASK_COUNT: usize = 10;
16
18
  #[pyclass(name = "ListStream", module = "tosnativeclient")]
17
19
  pub struct ListStream {
18
20
  client: Arc<InnerTosClient>,
@@ -58,13 +60,19 @@ impl ListStream {
58
60
  slf.next_page(pg.as_ref(), slf.py())
59
61
  }
60
62
 
61
- pub fn close(&self) {
62
- if let Ok(_) = self
63
+ pub fn close(slf: PyRef<'_, Self>) {
64
+ if let Ok(_) = slf
63
65
  .closed
64
66
  .compare_exchange(0, 1, Ordering::AcqRel, Ordering::Relaxed)
65
67
  {
66
- if let Some(pg) = self.paginator.read().unwrap().as_ref() {
68
+ if let Some(pg) = slf.paginator.write().unwrap().as_mut() {
67
69
  pg.receiver.close();
70
+ let runtime = slf.runtime.clone();
71
+ slf.py().allow_threads(|| {
72
+ runtime.block_on(async {
73
+ pg.close().await;
74
+ })
75
+ });
68
76
  }
69
77
  }
70
78
  }
@@ -124,7 +132,7 @@ impl ListStream {
124
132
  if self.start_after != "" {
125
133
  input.set_start_after(self.start_after.as_str());
126
134
  }
127
- py.allow_threads(|| {
135
+ let wait_list_background = py.allow_threads(|| {
128
136
  self.runtime.spawn(async move {
129
137
  let mut need_break = false;
130
138
  if input.delimiter() == "" {
@@ -181,7 +189,7 @@ impl ListStream {
181
189
  }
182
190
  }
183
191
  }
184
- });
192
+ })
185
193
  });
186
194
  Some(Paginator {
187
195
  is_end: ArcSwap::new(Arc::new(false)),
@@ -189,6 +197,7 @@ impl ListStream {
189
197
  current_prefix: ArcSwap::new(Arc::new(self.prefix.clone())),
190
198
  current_continuation_token: ArcSwap::new(Arc::new(self.continuation_token.clone())),
191
199
  receiver,
200
+ wait_list_background: Some(wait_list_background),
192
201
  })
193
202
  }
194
203
 
@@ -228,6 +237,7 @@ pub(crate) struct Paginator {
228
237
  current_prefix: ArcSwap<String>,
229
238
  current_continuation_token: ArcSwap<String>,
230
239
  receiver: Receiver<(bool, Result<ListObjectsType2Output, TosError>)>,
240
+ wait_list_background: Option<JoinHandle<()>>,
231
241
  }
232
242
 
233
243
  impl Paginator {
@@ -244,6 +254,13 @@ impl Paginator {
244
254
  fn current_continuation_token(&self) -> String {
245
255
  self.current_continuation_token.load().to_string()
246
256
  }
257
+
258
+ async fn close(&mut self) {
259
+ if let Some(wait_list_background) = self.wait_list_background.take() {
260
+ let _ = wait_list_background.await;
261
+ }
262
+ }
263
+
247
264
  async fn next_page(&self) -> Result<ListObjectsType2Output, TosError> {
248
265
  if let Some(e) = self.last_err.load().as_ref() {
249
266
  return Err(e.clone());
@@ -11,6 +11,7 @@ use std::sync::atomic::{AtomicI8, AtomicIsize, Ordering};
11
11
  use std::sync::Arc;
12
12
  use tokio::runtime::{Handle, Runtime};
13
13
  use tokio::sync::{Mutex, MutexGuard};
14
+ use tokio::task::JoinHandle;
14
15
  use tracing::log::{error, warn};
15
16
  use ve_tos_rust_sdk::asynchronous::object::ObjectAPI;
16
17
  use ve_tos_rust_sdk::error::TosError;
@@ -341,9 +342,9 @@ impl ObjectFetcher {
341
342
  return None;
342
343
  }
343
344
 
344
- let task = self.new_fetch_task(fc);
345
+ let mut task = self.new_fetch_task(fc);
345
346
  self.revise_next_request_offset_and_size(fc, task.size);
346
- task.async_fetch(self.client.clone(), runtime);
347
+ task.wait_async_fetch = Some(task.async_fetch(self.client.clone(), runtime));
347
348
  Some(task)
348
349
  }
349
350
 
@@ -512,6 +513,7 @@ impl ObjectFetcher {
512
513
  chunk_queue: Arc::new(ChunkQueue::new(self.calc_chunk_queue_size() as usize)),
513
514
  last_chunk: ChunkHolder::new(None),
514
515
  closed: self.closed.clone(),
516
+ wait_async_fetch: None,
515
517
  }
516
518
  }
517
519
 
@@ -537,6 +539,7 @@ impl ObjectFetcher {
537
539
  chunk_queue: Arc::new(ChunkQueue::new(chunks.len())),
538
540
  last_chunk: ChunkHolder { inner: None },
539
541
  closed: self.closed.clone(),
542
+ wait_async_fetch: None,
540
543
  };
541
544
 
542
545
  for chunk in chunks {
@@ -653,6 +656,7 @@ struct FetchTask {
653
656
  chunk_queue: Arc<ChunkQueue>,
654
657
  last_chunk: ChunkHolder,
655
658
  closed: Arc<AtomicI8>,
659
+ wait_async_fetch: Option<JoinHandle<()>>,
656
660
  }
657
661
 
658
662
  impl FetchTask {
@@ -666,12 +670,12 @@ impl FetchTask {
666
670
  self.start_offset + self.fetched_size.load(Ordering::Acquire)
667
671
  }
668
672
 
669
- fn async_fetch(&self, client: Arc<InnerTosClient>, runtime: Arc<Runtime>) {
673
+ fn async_fetch(&self, client: Arc<InnerTosClient>, runtime: Arc<Runtime>) -> JoinHandle<()> {
670
674
  let fetch_task_context = FetchTaskContext::new(self, client);
671
675
  runtime.spawn(async move {
672
676
  fetch_task_context.fetch_from_server().await;
673
677
  fetch_task_context.chunk_queue.close();
674
- });
678
+ })
675
679
  }
676
680
 
677
681
  async fn read(&mut self, length: isize) -> Option<Chunk> {
@@ -716,6 +720,9 @@ impl FetchTask {
716
720
  self.shared_prefetch_task.fetch_add(-1, Ordering::Release);
717
721
  self.pcontext.release_shared_prefetch_task();
718
722
  }
723
+ if let Some(wait_execute) = self.wait_async_fetch.take() {
724
+ let _ = wait_execute.await;
725
+ }
719
726
  }
720
727
  }
721
728
 
@@ -192,7 +192,7 @@ impl TosClient {
192
192
  runtime.block_on(async move {
193
193
  match client.head_object(&input).await {
194
194
  Err(ex) => Err(map_tos_error(ex)),
195
- Ok(output) => Ok(TosObject::new(input.bucket(), input.key(), output)),
195
+ Ok(output) => Ok(TosObject::inner_new(input.bucket(), input.key(), output)),
196
196
  }
197
197
  })
198
198
  })
@@ -1,4 +1,5 @@
1
- use pyo3::pyclass;
1
+ use pyo3::types::PyTuple;
2
+ use pyo3::{pyclass, pymethods, Bound, IntoPyObject, PyRef, PyResult};
2
3
  use ve_tos_rust_sdk::object::{HeadObjectOutput, ListObjectsType2Output};
3
4
 
4
5
  #[pyclass(name = "ListObjectsResult", module = "tosnativeclient")]
@@ -44,9 +45,32 @@ pub struct TosObject {
44
45
  #[pyo3(get)]
45
46
  pub(crate) etag: String,
46
47
  }
48
+ #[pymethods]
49
+ impl TosObject {
50
+ #[new]
51
+ #[pyo3(signature = (bucket, key, size, etag))]
52
+ pub fn new(bucket: String, key: String, size: isize, etag: String) -> Self {
53
+ Self {
54
+ bucket,
55
+ key,
56
+ size,
57
+ etag,
58
+ }
59
+ }
60
+ pub fn __getnewargs__(slf: PyRef<'_, Self>) -> PyResult<Bound<'_, PyTuple>> {
61
+ let py = slf.py();
62
+ let state = [
63
+ slf.bucket.clone().into_pyobject(py)?.into_any(),
64
+ slf.key.clone().into_pyobject(py)?.into_any(),
65
+ slf.size.into_pyobject(py)?.into_any(),
66
+ slf.etag.clone().into_pyobject(py)?.into_any(),
67
+ ];
68
+ PyTuple::new(py, state)
69
+ }
70
+ }
47
71
 
48
72
  impl TosObject {
49
- pub(crate) fn new(bucket: &str, key: &str, output: HeadObjectOutput) -> Self {
73
+ pub(crate) fn inner_new(bucket: &str, key: &str, output: HeadObjectOutput) -> Self {
50
74
  Self {
51
75
  bucket: bucket.to_string(),
52
76
  key: key.to_string(),