transaction.rs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. //! # Transaction command handlers
  2. use std::collections::VecDeque;
  3. use crate::{
  4. connection::{Connection, ConnectionStatus},
  5. error::Error,
  6. value::Value,
  7. };
  8. use bytes::Bytes;
  9. /// Flushes all previously queued commands in a transaction and restores the connection state to
  10. /// normal.
  11. ///
  12. /// If WATCH was used, DISCARD unwatches all keys watched by the connection
  13. pub async fn discard(conn: &Connection, _: VecDeque<Bytes>) -> Result<Value, Error> {
  14. conn.stop_transaction()
  15. }
  16. /// Marks the start of a transaction block. Subsequent commands will be queued for atomic execution
  17. /// using EXEC.
  18. pub async fn multi(conn: &Connection, _: VecDeque<Bytes>) -> Result<Value, Error> {
  19. conn.start_transaction()
  20. }
  21. /// Executes all previously queued commands in a transaction and restores the connection state to
  22. /// normal.
  23. ///
  24. /// When using WATCH, EXEC will execute commands only if the watched keys were not modified,
  25. /// allowing for a check-and-set mechanism.
  26. pub async fn exec(conn: &Connection, _: VecDeque<Bytes>) -> Result<Value, Error> {
  27. match conn.status() {
  28. ConnectionStatus::Multi => Ok(()),
  29. ConnectionStatus::FailedTx => {
  30. let _ = conn.stop_transaction();
  31. Err(Error::TxAborted)
  32. }
  33. _ => Err(Error::NotInTx),
  34. }?;
  35. if conn.did_keys_change() {
  36. let _ = conn.stop_transaction();
  37. return Ok(Value::Null);
  38. }
  39. let db = conn.db();
  40. let locked_keys = conn.get_tx_keys();
  41. db.lock_keys(&locked_keys);
  42. let mut results = vec![];
  43. if let Some(commands) = conn.get_queue_commands() {
  44. let dispatcher = conn.all_connections().get_dispatcher();
  45. for args in commands.into_iter() {
  46. let result = dispatcher
  47. .execute(conn, args)
  48. .await
  49. .unwrap_or_else(|x| x.into());
  50. results.push(result);
  51. }
  52. }
  53. db.unlock_keys(&locked_keys);
  54. let _ = conn.stop_transaction();
  55. Ok(results.into())
  56. }
  57. /// Marks the given keys to be watched for conditional execution of a transaction.
  58. pub async fn watch(conn: &Connection, args: VecDeque<Bytes>) -> Result<Value, Error> {
  59. if conn.status() == ConnectionStatus::Multi {
  60. return Err(Error::WatchInsideTx);
  61. }
  62. conn.watch_key(
  63. args.into_iter()
  64. .map(|key| {
  65. let v = conn.db().get_version(&key);
  66. (key, v)
  67. })
  68. .collect::<Vec<(Bytes, usize)>>(),
  69. );
  70. Ok(Value::Ok)
  71. }
  72. /// Flushes all the previously watched keys for a transaction.
  73. ///
  74. /// If you call EXEC or DISCARD, there's no need to manually call UNWATCH.
  75. pub async fn unwatch(conn: &Connection, _: VecDeque<Bytes>) -> Result<Value, Error> {
  76. conn.discard_watched_keys();
  77. Ok(Value::Ok)
  78. }
  79. #[cfg(test)]
  80. mod test {
  81. use std::collections::VecDeque;
  82. use crate::dispatcher::Dispatcher;
  83. use crate::{
  84. cmd::test::{create_connection, run_command},
  85. error::Error,
  86. value::Value,
  87. };
  88. use bytes::Bytes;
  89. #[tokio::test]
  90. async fn test_exec() {
  91. let c = create_connection();
  92. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  93. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  94. assert_eq!(
  95. Ok(Value::Queued),
  96. run_command(&c, &["set", "foo", "foo"]).await
  97. );
  98. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  99. assert_eq!(
  100. Ok(Value::Array(vec![
  101. Value::Null,
  102. Value::Ok,
  103. Value::Blob("foo".into()),
  104. ])),
  105. run_command(&c, &["exec"]).await
  106. );
  107. }
  108. #[tokio::test]
  109. async fn test_nested_multi() {
  110. let c = create_connection();
  111. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  112. assert_eq!(Err(Error::NestedTx), run_command(&c, &["multi"]).await);
  113. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  114. assert_eq!(
  115. Ok(Value::Queued),
  116. run_command(&c, &["set", "foo", "foo"]).await
  117. );
  118. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  119. assert_eq!(
  120. Ok(Value::Array(vec![
  121. Value::Null,
  122. Value::Ok,
  123. Value::Blob("foo".into()),
  124. ])),
  125. run_command(&c, &["exec"]).await
  126. );
  127. }
  128. #[tokio::test]
  129. async fn test_discard() {
  130. let c = create_connection();
  131. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  132. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  133. assert_eq!(
  134. Ok(Value::Queued),
  135. run_command(&c, &["set", "foo", "foo"]).await
  136. );
  137. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  138. assert_eq!(Ok(Value::Ok), run_command(&c, &["discard"]).await);
  139. assert_eq!(Err(Error::NotInTx), run_command(&c, &["exec"]).await);
  140. }
  141. #[tokio::test]
  142. async fn test_exec_watch_changes() {
  143. let c = create_connection();
  144. assert_eq!(
  145. Ok(Value::Ok),
  146. run_command(&c, &["watch", "foo", "bar"]).await
  147. );
  148. assert_eq!(Ok(Value::Ok), run_command(&c, &["set", "foo", "bar"]).await);
  149. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  150. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  151. assert_eq!(
  152. Ok(Value::Queued),
  153. run_command(&c, &["set", "foo", "foo"]).await
  154. );
  155. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  156. assert_eq!(Ok(Value::Null), run_command(&c, &["exec"]).await);
  157. }
  158. #[test]
  159. fn test_extract_keys() {
  160. assert_eq!(vec!["foo"], get_keys(&["get", "foo"]));
  161. assert_eq!(vec!["foo"], get_keys(&["set", "foo", "bar"]));
  162. assert_eq!(vec!["foo", "bar"], get_keys(&["mget", "foo", "bar"]));
  163. assert_eq!(
  164. vec!["key", "key1", "key2"],
  165. get_keys(&["SINTERSTORE", "key", "key1", "key2"])
  166. );
  167. }
  168. #[tokio::test]
  169. async fn test_exec_brpop_not_waiting() {
  170. let c = create_connection();
  171. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  172. assert_eq!(
  173. Ok(Value::Queued),
  174. run_command(&c, &["brpop", "foo", "1000"]).await
  175. );
  176. assert_eq!(
  177. Ok(Value::Array(vec![Value::Null,])),
  178. run_command(&c, &["exec"]).await
  179. );
  180. }
  181. #[tokio::test]
  182. async fn test_exec_blpop_not_waiting() {
  183. let c = create_connection();
  184. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  185. assert_eq!(
  186. Ok(Value::Queued),
  187. run_command(&c, &["blpop", "foo", "1000"]).await
  188. );
  189. assert_eq!(
  190. Ok(Value::Array(vec![Value::Null,])),
  191. run_command(&c, &["exec"]).await
  192. );
  193. }
  194. #[tokio::test]
  195. async fn test_two_consecutive_transactions() {
  196. let c = create_connection();
  197. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  198. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  199. assert_eq!(
  200. Ok(Value::Queued),
  201. run_command(&c, &["set", "foo", "foo"]).await
  202. );
  203. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  204. assert_eq!(
  205. Ok(Value::Array(vec![
  206. Value::Null,
  207. Value::Ok,
  208. Value::Blob("foo".into()),
  209. ])),
  210. run_command(&c, &["exec"]).await
  211. );
  212. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  213. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  214. assert_eq!(
  215. Ok(Value::Queued),
  216. run_command(&c, &["set", "foo", "bar"]).await
  217. );
  218. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  219. assert_eq!(
  220. Ok(Value::Array(vec![
  221. Value::Blob("foo".into()),
  222. Value::Ok,
  223. Value::Blob("bar".into()),
  224. ])),
  225. run_command(&c, &["exec"]).await
  226. );
  227. }
  228. #[tokio::test]
  229. async fn test_reset_drops_transaction() {
  230. let c = create_connection();
  231. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  232. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  233. assert_eq!(
  234. Ok(Value::Queued),
  235. run_command(&c, &["set", "foo", "foo"]).await
  236. );
  237. assert_eq!(Ok(Value::Queued), run_command(&c, &["get", "foo"]).await);
  238. assert_eq!(
  239. Ok(Value::String("RESET".into())),
  240. run_command(&c, &["reset"]).await
  241. );
  242. assert_eq!(Err(Error::NotInTx), run_command(&c, &["exec"]).await);
  243. }
  244. #[tokio::test]
  245. async fn test_exec_fails_abort() {
  246. let c = create_connection();
  247. assert_eq!(Ok(Value::Ok), run_command(&c, &["multi"]).await);
  248. assert_eq!(
  249. Err(Error::CommandNotFound("GETX".to_owned())),
  250. run_command(&c, &["getx", "foo"]).await
  251. );
  252. assert_eq!(
  253. Ok(Value::Queued),
  254. run_command(&c, &["set", "foo", "foo"]).await
  255. );
  256. assert_eq!(Err(Error::TxAborted), run_command(&c, &["exec"]).await,);
  257. assert_eq!(Err(Error::NotInTx), run_command(&c, &["exec"]).await,);
  258. }
  259. fn get_keys(args: &[&str]) -> Vec<Bytes> {
  260. let args: VecDeque<Bytes> = args.iter().map(|s| Bytes::from(s.to_string())).collect();
  261. let d = Dispatcher::new();
  262. d.get_handler(&args)
  263. .map(|cmd| cmd.get_keys(&args, true))
  264. .unwrap_or_default()
  265. }
  266. }