@@ -657,31 +657,40 @@ function M.upgrade(space,opts,depth)
657657 -- Producer should not be notified if queue is able to process task in future.
658658 local function notify_producer (key , task )
659659 local pkey = self :packkey (key )
660- local chan = self .put_wait [pkey ]
661- if not chan or not chan : has_readers () then
660+ local wait = self .put_wait [pkey ]
661+ if not wait then
662662 -- no producer
663663 return
664664 end
665+
665666 if task .status == ' Z' or task .status == ' D' then
666667 -- task was processed
667- chan :put ({ task , true }, 0 )
668+ wait .task = task
669+ wait .processed = true
670+ wait .cond :broadcast ()
668671 return
669672 end
670673 if not space :get {key } then
671674 -- task is not present in space
672675 -- it could be TTL or :ack
673676 if task .status == ' T' then
674677 -- task was acked:
675- chan :put ({ task , true }, 0 )
678+ wait .task = task
679+ wait .processed = true
680+ wait .cond :broadcast ()
676681 elseif task .status == ' R' then
677682 -- task was killed by TTL
678- chan :put ({ task , false }, 0 )
683+ wait .task = task
684+ wait .processed = false
685+ wait .cond :broadcast ()
679686 end
680687 else
681688 -- task is still in space
682689 if task .status == ' B' then
683690 -- task was buried
684- chan :put ({ task , false }, 0 )
691+ wait .task = task
692+ wait .processed = false
693+ wait .cond :broadcast ()
685694 end
686695 end
687696 end
@@ -1098,29 +1107,73 @@ function methods:put(t, opts)
10981107 local tuple = xq .tuple (t )
10991108 local key = tuple [ xq .key .no ]
11001109
1101- local chan
1110+ local wait
11021111 if opts .wait then
1103- chan = fiber .channel ( 1 )
1104- xq .put_wait [xq :packkey (key )] = chan
1112+ wait = { cond = fiber .cond () }
1113+ xq .put_wait [xq :packkey (key )] = wait
11051114 end
11061115
11071116 xq :atomic (key , function ()
11081117 t = self :insert (tuple )
11091118 end )
11101119 xq :wakeup (t )
11111120
1112- if chan then
1121+ if wait then
11131122 -- local func notify_producer will send to us some data
1114- local msg = chan :get (opts .wait )
1115- if msg then
1116- xq .put_wait [xq :packkey (key )] = nil
1117- chan :close ()
1118- return xq .retwrap (msg [1 ]), msg [2 ]
1123+ local ok = wait .cond :wait (opts .wait )
1124+ fiber .testcancel ()
1125+ if ok and wait .task then
1126+ return xq .retwrap (wait .task ), wait .processed
11191127 end
11201128 end
11211129 return xq .retwrap (t )
11221130end
11231131
1132+ --[[
1133+ * `space:wait(id, timeout)`
1134+ - `id`:
1135+ + `string` | `number` - primary key
1136+ - `timeout` - number of seconds to wait
1137+ * callee fiber will be blocked up to `timeout` seconds until task won't
1138+ be processed or timeout reached.
1139+ ]]
1140+
1141+ local wait_for = {
1142+ R = true ,
1143+ T = true ,
1144+ W = true ,
1145+ }
1146+
1147+ function methods :wait (key , timeout )
1148+ local xq = self .xq
1149+ key = xq :getkey (key )
1150+ local task = self :get (key )
1151+ if not task then
1152+ error ((" Task {%s} was not found" ):format (key ))
1153+ end
1154+
1155+ local status = task [xq .fields .status ]
1156+ if not wait_for [status ] then
1157+ return xq .retwrap (task ), false
1158+ end
1159+
1160+ local pkey = xq :packkey (key )
1161+ local wait = xq .put_wait [pkey ]
1162+ if not wait then
1163+ wait = { cond = fiber .cond () }
1164+ xq .put_wait [pkey ] = wait
1165+ end
1166+
1167+ -- local func notify_producer will send to us some data
1168+ local ok = wait .cond :wait (timeout )
1169+ fiber .testcancel ()
1170+ if ok and wait .task then
1171+ return xq .retwrap (wait .task ), wait .processed
1172+ end
1173+
1174+ return xq .retwrap (task ), false
1175+ end
1176+
11241177--[[
11251178* `space:take(timeout)`
11261179* `space:take(timeout, opts)`
0 commit comments