Closed ghost closed 3 years ago
Hi @bruno-barin-ifood , Can you please provide me with a code snipped that reproduces this behaviour?
Sure, here you are:
use cdrs::frame::Frame;
use cdrs::query::*;
use cdrs::types::prelude::*;
use log::error;
use rdkafka::consumer::Consumer;
use rdkafka::Message;
use model::Cart;
use settings::*;
mod model;
mod settings;
fn main() {
env_logger::init();
consume_messages();
}
const UPDATE_QUERY: &str = "UPDATE cart.carts SET cart = ?, status = ? WHERE id = ?";
struct Scylla {
prepared_query: PreparedQuery,
scylla_session: ScyllaSession
}
impl Scylla {
fn new() -> Self {
let prepared_query = self.scylla_session.prepare(UPDATE_QUERY).unwrap();
let scylla_session = get_scylla_session();
Scylla {
prepared_query,
scylla_session
}
}
fn update_scylla(&self, cart: &Cart) -> Result<Frame> {
self.scylla_session.exec_with_values(&self.prepared_query, cart.into_query_values())
}
}
fn consume_messages() {
let kafka_consumer = kafka_consumer();
let scylla = Scylla::new();
for potential_message in kafka_consumer.iter() {
match potential_message {
Err(e) => error!("Error to fetch message from Kafka. Reason: {}", e),
Ok(message) => {
let body = message.payload_view().unwrap().unwrap();
let cart: Cart = serde_json::from_str(body).unwrap();
let result = scylla.update_scylla(&cart);
match result {
Ok(_) => {
kafka_consumer.store_offset(&message)
.expect("Failed to commit message to Kafka");
}
Err(_err) => println!("Cart {} failed due to connection problems - {}", cart.id, _err)
}
}
}
}
}
The link for the issue I've opened to the Scylla team is this one:
@bruno-barin-ifood If you have a cluster with more than one Scylla/Cassandra nodes it may be problematic to execute prepared queries with current CDRS implementation - during the next request to cluster next or random node (depending on the balancing strategy) will be used so it may lead to the situation when such not doesn't have a corresponded prepared query registered. So it that regards CDRS may need some improvements
thanks @AlexPikalov !
Please note this can happen also in a single node, that is a Cassandra/Scylla node may invalidate the prepared statements (due to some internal reasons).
When a prepared statement will be executed the error of not having the prepared statement will be returned (https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec#L1169)
Most drivers at this point reprepare the statement and following that reexecute it.
So while it would be preferable to prepare a statement on all connections (to make sure its avail) yet this is not a must, it would be sufficient to handle the error and reexecute the statement.
@bruno-barin-ifood I've just read the conversation inside the issue that you've created for Scylla.
@slivne Got you. It's an interesting fact which was not known to me before.
I think I need to think how to make the driver smarter in that regards.
Hi @AlexPikalov do you have any progress with this issue?
is it possible to add a specific error for this?
I guess a work around for now is to just query directly with the prepared statement.
Hi! Get this error when trying to update a CF multiple times in Scylla. I filed an issued to scylla and attached a tcpdump showing the traffic between the driver and the database. The Scylla team said it's a problem with the driver that's ignoring the error coming from Scylla (seems there's a cache for prepared statements and from time to time it gets evicted) instead of retrying to reprepare the statement.