ra1u / redis-dart

fast redis protocol parser and client
MIT License
84 stars 35 forks source link

Exception when using large number of commands in a transaction #1

Closed alexschneider closed 9 years ago

alexschneider commented 9 years ago

While building my app here: https://github.com/alexschneider/pub-search-engine

I decided to use this redis library because it has support for transactions, unlike the other one.

However, it appears that transactions fail with the exception:

Unhandled exception:
Uncaught Error: Bad state: No element
Stack Trace:
#0      ListQueue.removeFirst (dart:collection/queue.dart:555)
#1      Transaction.exec.<anonymous closure> (package:redis/transaction.dart:33:42)
#2      _RootZone.runUnary (dart:async/zone.dart:1155)
#3      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#4      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#5      _Future._complete (dart:async/future_impl.dart:348)
#6      _SyncCompleter.complete (dart:async/future_impl.dart:52)
#7      RedisConnection.senddummy.<anonymous closure>.<anonymous closure> (package:redis/connection.dart:35:40)
#8      _RootZone.runUnary (dart:async/zone.dart:1155)
#9      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#10     _Future._propagateToListeners (dart:async/future_impl.dart:567)
#11     _Future._completeWithValue (dart:async/future_impl.dart:358)
#12     _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:412)
#13     _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#14     _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#15     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#16     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)

or if run in checked mode:

Unhandled exception:
Uncaught Error: 'package:redis/transaction.dart': Failed assertion: line 30 pos 16: 'list.length == _queue.length' is not true.
Stack Trace:
#0      Transaction.exec.<anonymous closure> (package:redis/transaction.dart:30:16)
#1      _RootZone.runUnary (dart:async/zone.dart:1155)
#2      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#3      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#4      _Future._complete (dart:async/future_impl.dart:348)
#5      _SyncCompleter.complete (dart:async/future_impl.dart:52)
#6      RedisConnection.senddummy.<anonymous closure>.<anonymous closure> (package:redis/connection.dart:35:40)
#7      _RootZone.runUnary (dart:async/zone.dart:1155)
#8      _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:484)
#9      _Future._propagateToListeners (dart:async/future_impl.dart:567)
#10     _Future._completeWithValue (dart:async/future_impl.dart:358)
#11     _Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:412)
#12     _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#13     _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#14     _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#15     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)

#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:886)
#1      _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:41)
#2      _asyncRunCallback (dart:async/schedule_microtask.dart:48)
#3      _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:84)
#4      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:131)

You can replicate my results by cloning my repo, cding to bin/ and running dart server.dart.

It appears to be an off by one error somewhere, when I checked in the debugger, list had one more item than _queue, and that the first two items appeared to be "OK" in list, not sure if there's an extra "OK" in there or not...

ra1u commented 9 years ago

Once you start transaction, you cant kick any other command trough this connection untill it is finished, All commands you send, have to go trough transactions. Can you check whenever this is issue in your code?

ra1u commented 9 years ago

Issue is as I expected, that set was executed before transaction completes trough connection handler. patch : https://github.com/ra1u/pub-search-engine/commit/8845b5acb34f2061afc58be487754b616727e7f1

ra1u commented 9 years ago

Latest master version throw error if original Command is used during transaction at point where Command is used.