╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Issue.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
58 // drop the old tags' entries; the current tags are re-added below 59 const order_key = evt.orderKey(existing_event.created_ts, event_id); 60 try removeFromTagSets(DB, tag_to_issues, existing_event.tags, &order_key); 61 } else { 62 // first time we've seen this issue: stamp it with the commit timestamp 63 event_to_write.created_ts = created_ts; 64 } 65 66 const issue_cursor = try event_id_to_issue.putCursor(issue_key); 67 const issue = try DB.HashMap(.read_write).init(issue_cursor); 68 try evt.upsert(@This(), DB, hash_kind, issue, event_to_write); 69 70 const order_key = evt.orderKey(event_to_write.created_ts, event_id); 71 72 var tag_iter = tagIterator(event.tags); 73 while (tag_iter.next()) |tag| { 74 if (tag.len == 0) continue; 75 if (tag.len > tag_max_len) return error.TagTooLong; 76 const tag_set_cursor = try tag_to_issues.putCursor(tag); 77 const tag_set = try DB.SortedSet(.read_write).init(tag_set_cursor); 78 try tag_set.put(&order_key); 79 } 80 81 // first time we've seen this issue: add it to the set the issues view 82 // lists, ordered by creation time. the key (orderKey) embeds the event 83 // id, so the set needs no value. 84 if (existing_cursor_maybe == null) { 85 const issue_id_set_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "issue-id-set")); 86 const issue_id_set = try DB.SortedSet(.read_write).init(issue_id_set_cursor); 87 try issue_id_set.put(&order_key); 88 } 89 } else { 90 // drop it from the ordered sets using its recorded creation timestamp 91 if (try event_id_to_issue.getCursor(issue_key)) |existing_cursor| { 92 const existing_issue = try DB.HashMap(.read_only).init(existing_cursor); 93 const existing_event = try evt.read(@This(), DB, hash_kind, arena, existing_issue); 94 const order_key = evt.orderKey(existing_event.created_ts, event_id); 95 96 const issue_id_set_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "issue-id-set")); 97 const issue_id_set = try DB.SortedSet(.read_write).init(issue_id_set_cursor); 98 _ = try issue_id_set.remove(&order_key); 99 100 try removeFromTagSets(DB, tag_to_issues, existing_event.tags, &order_key); 101 } 102 if (!try event_id_to_issue.remove(issue_key)) return error.EventNotFound; 103 } 104 } 105 106 // remove an issue's order key from each of its tags' sets, pruning tags whose 107 // set becomes empty. 108 fn removeFromTagSets( 109 comptime DB: type, 110 tag_to_issues: DB.SortedMap(.read_write), 111 tags: []const u8, 112 order_key: []const u8, 113 ) !void { 114 var tag_iter = tagIterator(tags); 115 while (tag_iter.next()) |tag| { 116 if (tag.len == 0) continue; 117 const tag_set_cursor = try tag_to_issues.putCursor(tag); 118 const tag_set = try DB.SortedSet(.read_write).init(tag_set_cursor); 119 _ = try tag_set.remove(order_key); 120 if (0 == try tag_set.count()) _ = try tag_to_issues.remove(tag); 121 } 122 } 123