ydb-platform / ydb-rs-sdk

Apache License 2.0
51 stars 18 forks source link

Bad Session Error #66

Open avkviring opened 2 years ago

avkviring commented 2 years ago

Hi

Periodically I see this errors

YdbStatusError(YdbStatusError { message: "Operation { id: \"\", ready: true, status: BadSession, issues: [IssueMessage { position: None, message: \"Session not found: ydb://session/3?node_id=1025&id=Y2JlZWIxNTEtNTdkYzE0NTktZDM0NDg4MjYtYWQ5ZjVmODM=\", end_position: None, issue_code: 0, severity: 1, issues: [] }], result: None, metadata: None, cost_info: None }", operation_status: 400100, issues: [YdbIssue { issue_code: 0, message: "Session not found: ydb://session/3?node_id=1025&id=Y2JlZWIxNTEtNTdkYzE0NTktZDM0NDg4MjYtYWQ5ZjVmODM=", issues: [], severity: 1 }] })

In this function

pub async fn find(&self, cookie: &Cookie) -> Result<Option<User>, YdbOrCustomerError> {
        let result: Vec<User> = select!(
            self.ydb_table_client,
            query!("select user from cookie_users where cookie=$cookie", cookie=>cookie),
            user => Bytes)
        .await?;
        Ok(result.into_iter().last())
    }
rekby commented 2 years ago

Hello, can you expand select! and query! macroses?

BadSession is retriable status and retry_transaction must retry query with new session if your callback return YdbError::YdbStatusError with BadSession status.

cause of the messages can be:

  1. Bug in SDK - and SDK not retry the error.
  2. Bug in macros - if macros return from query callback Custom Error instead of original YdbError (then retrier can't detect original error for retry)
  3. End of retries timeout (small retry timeout and/or many died session on server side).
avkviring commented 2 years ago
#[macro_export]
macro_rules! select {
    ($ydb:expr, $query:expr, $($name:ident => $type:ty),* ) => {{
        $ydb.retry_transaction(|mut t| async move {
            let query_result = t.query($query).await?;
            let result_set = query_result.into_only_result()?;
            let result:Vec<_> = result_set.rows().map(|mut row| {
                $(
                    let $name:Option<$type>  = row.remove_field_by_name(stringify!($name)).unwrap().try_into().unwrap();
                )*
                ($($name.unwrap().into()),*)
            }).collect();
            Ok(result)
        })
    }};
}

#[macro_export]
macro_rules! query {
    ($sql:expr) => {{
            ydb::Query::new($sql)
    }};
    ($sql:expr, $($name:ident => $value:expr),*) => {{
            let mut query = String::new();
            let mut params: std::collections::HashMap<String, ydb::Value> = Default::default();
            $(
                {
                    let value = &$value;
                    let name = stringify!($name);
                    let type_name = $crate::converters::YDBValueConverter::get_type_name(value);
                    let ydb_value =$crate::converters::YDBValueConverter::to_ydb_value(value);
                    params.insert(format!("${}",name), ydb_value);
                    query.push_str(format!("declare ${} as {};\n",name,type_name).as_str());
                }
            )*
            ydb::Query::new(format!("{}\n{}",query, $sql)).with_params(params)
    }};
}
avkviring commented 2 years ago

End of retries timeout (small retry timeout and/or many died session on server side).

I use standard timeout, and service is not highload yet

avkviring commented 2 years ago

May be problem in NeedRetry::IdempotentOnly? I already understood what not :-)

rekby commented 2 years ago

I add tracing to retry_transaction for understand what happens.

Can you add tracing/logging to your program (example), update ydb to version 0.3.0 and show log?

avkviring commented 2 years ago

Hi, I have small holidays. I do it in few days.

Also I open my library for all - https://crates.io/crates/ydb-steroids