-
Notifications
You must be signed in to change notification settings - Fork 59
Syntax Wishlist
jhellerstein edited this page Jun 1, 2011
·
14 revisions
- Upsert. (Issue #71). Example without it:
finger <+ (fix_finger_finder.succ_resp * finger).pairs(:key => :start) do |s,f|
[f.index, f.start, f.hi, s.start, s.addr] unless s.start == f.succ
end
finger <- (fix_finger_finder.succ_resp * finger).pairs(:key => :start) do |s,f|
f unless s.start == f.succ
end
- simplify interaction with async interfaces. (Issue #17) Current example of caller side:
import ChordFind => :join_finder
# cache the request
join_pending <= join_req
# asynchronously, find out who owns start+1
join_finder.succ_req <= join_req.map{|j| [j.start+1]}
# upon response to successor request, issue a msg.
msg <~ (join_pending * join_finder.succ_resp).pairs do |j, s|
[s.addr, j.requestor_addr] if j.start+1 == s.key
end
similarly, simplify heartbeat/retry/timeout
# ask each successor for its predecessor every time stable_timer fires
temp :spr <= (stable_timer * other_succs).rights do |s|
[s.addr, ip_port] unless s.addr.nil?
end
succ_pred_req <~ spr
succ_pred_pending <= spr{|s| [s[0], budtime]}
# timeout after 5 secs
sfail <= (succ_pred_pending * stable_timer).pairs do |p,t|
[p.addr] if (Time.now - t.val) > 5
end
# clean up pending
succ_pred_pending <- (succ_pred_pending * succ_pred_resp).lefts(:addr => :from)
succ_pred_pending <- (sfail * succ_pred_pending).rights(:addr => :addr)
- allow variables (one-row relations) to be handled without explicit joins. (Issue #183). Current syntax:
table :me, [] => [:start, :pred_id, :pred_addr]
node_pred_resp <~ (finger_table_req * me).pairs do |f, m|
[f.requestor_addr, m.start, m.pred_id, m.pred_addr, ip_port]
end
or
node_pred_resp <~ finger_table_req do |f|
[f.requestor_addr, me.first.start, me.first.pred_id, me.first.pred_addr, ip_port] unless me.first.nil?
end
- support conditionals around rules (Issue #207). Currently we achieve this by mutually-exclusive predicates buried inside multiple rule bodies. This example has two rules. The 1st rule has two cases within a single rule, which works because they share a head. The second rule happens to be the "else" of the first rule, with a different head.
# we can respond locally for keys that are here or at our successor
find_resp <~ find_event do |e|
start = nil
# if at successor:
if at_successor(e.key)
if e.pred_or_succ == 'pred'
start = me.first.start; addr = ip_port
elsif e.pred_or_succ == 'succ' and finger[[0]] and not finger[[0]].succ.nil?
start = finger[[0]].succ; addr = finger[[0]].succ_addr
end
# else if local:
elsif at_local(e.key)
if e.pred_or_succ == 'pred'
start = me.first.pred_id; addr = me.first.pred_addr
elsif e.pred_or_succ == 'succ'
start = me.first.start; addr = ip_port
end
end
[e.from, e.key, e.pred_or_succ, start, addr] unless start.nil?
end
# for keys that are not at successor, forward to closest finger
find_req <~ (find_event * closest).combos(:key => :key) do |e, c|
[c.succ_addr, e.key, e.from, e.pred_or_succ] unless at_successor(e.key) or at_local(e.key)
end
As a form of conditionals around rules, nested joins would be nice. E.g. I want a whole pile of rules to only fire on a particular periodic, and it's annoying to have that content-free periodic collection joined into each rule.
- Support "soft idempotent" interfaces and/or channels. I.e. avoid resending requests until we timeout on the first try.
# no example here yet but this code makes markdown happy
- Syntax sugar to avoid having to wrap strings destined for stdio in []. Currently this is an error:
stdio <~ event { |e| "got event!" }
- Syntax sugar for hash lookups on singleton keys. Currently the first of these rule bodies silently never outputs anything, but the second does for any tuple with 0 in the first field:
table :finger
stdio <~ event { |e| puts "yay" unless finger[0].nil? }
stdio <~ event { |e| puts "hooray" unless finger[[0]].nil? }