|
1 | | -/* |
2 | | - * Licensed to the Apache Software Foundation (ASF) under one or more |
3 | | - * contributor license agreements. See the NOTICE file distributed with |
4 | | - * this work for additional information regarding copyright ownership. |
5 | | - * The ASF licenses this file to You under the Apache License, Version 2.0 |
6 | | - * (the "License"); you may not use this file except in compliance with |
7 | | - * the License. You may obtain a copy of the License at |
8 | | - * |
9 | | - * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | - * |
11 | | - * Unless required by applicable law or agreed to in writing, software |
12 | | - * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | - * See the License for the specific language governing permissions and |
15 | | - * limitations under the License. |
16 | | - */ |
17 | | -use std::sync::atomic::AtomicI32; |
| 1 | +use std::sync::atomic::AtomicU32; |
| 2 | +use std::sync::atomic::AtomicU64; |
18 | 3 | use std::sync::atomic::Ordering; |
19 | 4 | use std::sync::Arc; |
20 | 5 |
|
21 | | -use rocketmq_rust::RocketMQBlockingQueue; |
22 | | -use tokio::sync::Mutex; |
| 6 | +use anyhow::Error; |
| 7 | +use rocketmq_error::Result; |
| 8 | +use tokio::sync::mpsc; |
| 9 | +use tokio::time; |
23 | 10 |
|
24 | 11 | pub struct MessageQueueOpContext { |
25 | | - total_size: AtomicI32, |
26 | | - last_write_timestamp: Arc<Mutex<u64>>, |
27 | | - context_queue: RocketMQBlockingQueue<String>, |
| 12 | + total_size: AtomicU32, |
| 13 | + last_write_timestamp: AtomicU64, |
| 14 | + context_queue: Arc<mpsc::UnboundedSender<String>>, |
| 15 | + context_receiver: mpsc::UnboundedReceiver<String>, |
| 16 | + queue_capacity: usize, |
28 | 17 | } |
29 | 18 |
|
30 | 19 | impl MessageQueueOpContext { |
31 | 20 | pub fn new(timestamp: u64, queue_length: usize) -> Self { |
| 21 | + let unbounded_channel = mpsc::unbounded_channel::<String>(); |
32 | 22 | MessageQueueOpContext { |
33 | | - total_size: AtomicI32::new(0), |
34 | | - last_write_timestamp: Arc::new(Mutex::new(timestamp)), |
35 | | - context_queue: RocketMQBlockingQueue::new(queue_length), |
| 23 | + total_size: AtomicU32::new(0), |
| 24 | + last_write_timestamp: AtomicU64::new(timestamp), |
| 25 | + context_queue: Arc::new(unbounded_channel.0), |
| 26 | + context_receiver: unbounded_channel.1, |
| 27 | + queue_capacity: queue_length, |
36 | 28 | } |
37 | 29 | } |
38 | 30 |
|
39 | | - pub fn get_total_size(&self) -> i32 { |
| 31 | + pub async fn get_total_size(&self) -> u32 { |
40 | 32 | self.total_size.load(Ordering::Relaxed) |
41 | 33 | } |
42 | 34 |
|
43 | | - pub fn total_size_add_and_get(&self, delta: i32) -> i32 { |
| 35 | + pub async fn total_size_add_and_get(&self, delta: u32) -> u32 { |
44 | 36 | self.total_size.fetch_add(delta, Ordering::AcqRel) + delta |
45 | 37 | } |
46 | 38 |
|
47 | 39 | pub async fn get_last_write_timestamp(&self) -> u64 { |
48 | | - *self.last_write_timestamp.lock().await |
| 40 | + self.last_write_timestamp.load(Ordering::Relaxed) |
49 | 41 | } |
50 | 42 |
|
51 | 43 | pub async fn set_last_write_timestamp(&self, timestamp: u64) { |
52 | | - let mut last_timestamp = self.last_write_timestamp.lock().await; |
53 | | - *last_timestamp = timestamp; |
| 44 | + self.last_write_timestamp |
| 45 | + .store(timestamp, Ordering::Release); |
54 | 46 | } |
55 | 47 |
|
56 | | - pub fn context_queue(&self) -> &RocketMQBlockingQueue<String> { |
57 | | - &self.context_queue |
| 48 | + pub async fn push(&self, msg: String) -> Result<()> { |
| 49 | + if self.context_receiver.len() > self.queue_capacity { |
| 50 | + return Err(anyhow::Error::msg("queue is full".to_string())); |
| 51 | + } |
| 52 | + self.context_queue |
| 53 | + .send(msg) |
| 54 | + .map_err(|e| anyhow::Error::new(e)) |
| 55 | + } |
| 56 | + pub async fn offer(&self, item: String, timeout: std::time::Duration) -> Result<()> { |
| 57 | + time::timeout(timeout, self.push(item)).await.unwrap() |
| 58 | + } |
| 59 | + pub async fn pull(&mut self) -> Result<String> { |
| 60 | + if let Some(item) = self.context_receiver.recv().await { |
| 61 | + return Ok(item); |
| 62 | + } |
| 63 | + Err(Error::msg("pull failed, queue is empty".to_string())) |
| 64 | + } |
| 65 | + pub async fn is_empty(&self) -> bool { |
| 66 | + if self.context_receiver.len() == 0 { |
| 67 | + return true; |
| 68 | + } |
| 69 | + false |
58 | 70 | } |
59 | 71 | } |
0 commit comments