Comments (16)
Can you post a reproducible example?
from redis-rs.
I have tried reproducing on a test function, everything seems to be working fine there somehow.
The only difference from my code and the test function, is that I'm passing the ConnectionManager to a TypeMap, everything else functionality wise is the same.
To give a little bit more context on what I am doing, I am building a discord bot with serenity-rs and using this library (redis-rs) to fetch json objects.
Here is my test function
#[cfg(test)]
mod tests {
use std::time::Duration;
use redis::aio::ConnectionLike;
use redis::{aio::ConnectionManager, JsonAsyncCommands};
use serenity::all::InteractionType;
use crate::database::{InteractionStepKind, InteractionStep};
use crate::slash_command::SlashCommandFunctionality;
use crate::payload::captcha::UpdateSettings;
#[tokio::test]
async fn redis_json_get() {
// Init redis
let host = "127.0.0.1";
let port = 6379;
let user = "default";
let password = "development";
let database = 0;
let client = redis::Client::open(format!("redis://{}:{}@{}:{}/{}", user, password, host, port, database)).unwrap();
let mut conn_manager = ConnectionManager::new_with_backoff(client, 2, 2, 5).await.unwrap();
let object = InteractionStep::new(
&ulid::Ulid::new().to_string(),
InteractionStepKind::ConfirmAction { confirm_button_id: "aaa".to_string(), cancel_button_id: "bbb".to_string() },
SlashCommandFunctionality::UpdateCaptchaSettings(UpdateSettings { enabled: false, verified_role_id: Some(0000000), unverified_role_id: Some(111111) }),
InteractionType::Component,
00000000000000,
);
// JSON.SET
let mut pipeline = redis::pipe();
pipeline.json_set(&object.id, "$", &object).unwrap()
.cmd("EXPIRE").arg(&object.id).arg(60).ignore();
conn_manager.req_packed_commands(&pipeline, 0, 2).await.unwrap();
tokio::time::sleep(Duration::from_secs(30)).await;
// JSON.GET
let object_fetched : InteractionStep = conn_manager.json_get(&object.id, "$").await.unwrap();
assert_eq!(object, object_fetched)
}
}
from redis-rs.
I seem to have found the origin of the issue, I am not aware of what it is specifically but.
There might be something wrong with the implementation of ConnectionLike and subsequently JsonAsyncCommands for ConnectionManager.
This was my previous function wrapper over json_get, which was giving me the unexpected behavior above
As soon as I removed the generic parameter and defined the type as ConnectionManager, things started working as expected again.
EDIT
I have managed to reproduce the unexpected behavior, it seems that its my issue due to defining the count
argument on the req_packed_commands
in an incorrect way.
I did think by calling ignore()
on a command of the pipeline would make it so that specific command's response would not be read by the connection. It seems like it is, and if I set the count less to the amount of responses available, they will be eventually read by the json_get
functionality, making it so it responds with an unexpected value.
Here is the test code
#[cfg(test)]
mod tests {
use std::time::Duration;
use redis::aio::ConnectionLike;
use redis::{aio::ConnectionManager, JsonAsyncCommands};
use serenity::all::InteractionType;
use crate::database::{InteractionStepKind, InteractionStep};
use crate::slash_command::SlashCommandFunctionality;
use crate::payload::captcha::UpdateSettings;
async fn json_get_wrapper<C: JsonAsyncCommands>(id: &str, c: &mut C) -> InteractionStep {
c.json_get(id, "$").await.unwrap()
}
async fn json_set_wrapper<C: ConnectionLike>(object: &InteractionStep, conn: &mut C) {
let mut pipeline = redis::pipe();
pipeline.json_set(&object.id, "$", &object).unwrap()
.cmd("EXPIRE").arg(&object.id).arg(60).ignore();
conn.req_packed_commands(&pipeline, 0, 1).await.unwrap();
}
#[tokio::test]
async fn redis_json_get() {
// Init redis
let host = "127.0.0.1";
let port = 6379;
let user = "default";
let password = "development";
let database = 0;
let client = redis::Client::open(format!("redis://{}:{}@{}:{}/{}", user, password, host, port, database)).unwrap();
let mut conn_manager = ConnectionManager::new_with_backoff(client, 2, 2, 5).await.unwrap();
let object = InteractionStep::new(
&ulid::Ulid::new().to_string(),
InteractionStepKind::ConfirmAction { confirm_button_id: "aaa".to_string(), cancel_button_id: "bbb".to_string() },
SlashCommandFunctionality::UpdateCaptchaSettings(UpdateSettings { enabled: false, verified_role_id: Some(0000000), unverified_role_id: Some(111111) }),
InteractionType::Component,
00000000000000,
);
// JSON.SET
json_set_wrapper(&object, &mut conn_manager).await;
tokio::time::sleep(Duration::from_secs(20)).await;
// JSON.GET
let object_fetched : InteractionStep = json_get_wrapper(&object.id, &mut conn_manager).await;
assert_eq!(object, object_fetched)
}
}
from redis-rs.
Yes, the req_packed_commands
arguments are a bit confusing - essentially, mostly the offset & count arguments have only 2 correct options - either (0, \<num of commands\>)
for non-atomic pipelines, or (\<num of commands\> + 1, 1)
for atomic pipelines. Ignored commands don't matter here.
It seems to me like the function was intended to be internal to the crate, and is supposed to be used in the pipeline's query/query_async
function.
@jaymell We can definitely improve the command's documentation to reflect this, but if we're ok with breaking backwards compatibility about this, IMO we should hide this function from the users. It's a bit of a footgun.
from redis-rs.
@nihohit Thanks for the information, yeah it's definitely a bit confusing.
I wasn't aware that ignoring commands on the pipeline wouldn't count when using that same pipeline in the req_packed_commands
.
So from what I understood, calling the ignore()
function on a command, only works as intended when query/query_async
pipeline's functions are called, is that right?
from redis-rs.
@x1qqq query/query_async/execute are the correct interfaces.
from redis-rs.
@x1qqq, can this issue be closed?
from redis-rs.
I am also experiencing a similar error, I am trying to create a simple example at the moment.
from redis-rs.
@mrjackwills are you also using req_packed_commands
?
from redis-rs.
@mrjackwills are you also using
req_packed_commands
?
No, I'm using the simple AsyncCommands
. I am trying to debug at the moment, I think my issue might be related to the TTL command, but there are many layers to try to delve through.
from redis-rs.
Ok, so I have finally worked out the issue, I was using the wrong connection type.
I should have been using a ConnectionManager
rather then Connection
. As this connection is being shared in a multi-threaded API backend. So far, this seems to have solved the issues I was having.
from redis-rs.
redis: Response was of incompatible type - TypeError: "Response type not string compatible." (response was int(1)
redis: Response was of incompatible type - TypeError: "Response type not bool compatible." (response was string-data('"{\"id\":16,\"devices\":300,\"is_active\":true,\"online\":0}"'))
And i don't know how reproduced it
What intersting is errors from prod
but local and staging is good working
from redis-rs.
@Cheban1996 what's the issue? Int isn't string compatible, and strings aren't bool compatible.
from redis-rs.
@nihohit It was noticed that there are no problems at low loads. But when the load is heavy, instead of the expected data for a certain type, we get something completely different - as if from a different pool.
For greater understanding, I also use bb8-redis = "0.14.0" to pull threads. It looks like the problem is related to out of sync responses between threads. When we expect one thing and get another from another stream
from redis-rs.
what connection type do you use?
if it's aio::Connection
, it's deprecated - use aio::MultiplexedConnection
.
from redis-rs.
@nihohit Thank you so much
It's resolve my trouble
from redis-rs.
Related Issues (20)
- Async Cluster: Connection errors are hard to discover HOT 3
- Async Cluster: AWS Failover takes a long time to recover HOT 6
- `TlsConnParams` is opaque: Intentional? HOT 4
- add sentinel support in readme HOT 2
- Read timeouts on ConnectionManager in aio.rs HOT 6
- allow disabling setinfo HOT 2
- Compile error: error[E0277]: `ActualConnection` doesn't implement `Debug` HOT 1
- Does `ClusterClient::new()` work with ElastiCache's configuration endpoint? HOT 3
- Cannot use set or publish on Redis Async HOT 4
- Async Cluster: Connection is created on each request HOT 6
- Opt-out client set info when creating new connection HOT 4
- execute config get databases error HOT 2
- Redis deletion is slow or some weird caching is enabled HOT 8
- redis execute `rpop` command got block HOT 10
- Backwards incompatible changes to consider HOT 14
- Unable to reuse a `SetOptions` instance after first command HOT 1
- Breaking Change HOT 7
- Async pubsub subscription misses messages HOT 3
- pubsub subscription with channel(2) but get data when channel full HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from redis-rs.