╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Issue.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
83 const status_set = try statusSet(DB, status_to_issues, existing_event.status); 84 _ = try status_set.remove(&order_key); 85 try removeFromTagSets(DB, tag_to_issues, existing_event.tags, existing_event.status, &order_key); 86 } else { 87 // first time we've seen this issue: stamp it with the commit timestamp 88 event_to_write.created_ts = created_ts; 89 } 90 91 const issue_cursor = try event_id_to_issue.putCursor(issue_key); 92 const issue = try DB.HashMap(.read_write).init(issue_cursor); 93 try evt.upsert(@This(), DB, hash_kind, issue, event_to_write); 94 95 const order_key = evt.orderKey(event_to_write.created_ts, event_id); 96 97 const status_set = try statusSet(DB, status_to_issues, event.status); 98 try status_set.put(&order_key); 99 100 var tag_iter = tagIterator(event.tags); 101 while (tag_iter.next()) |tag| { 102 if (tag.len == 0) continue; 103 if (tag.len > tag_max_len) return error.TagTooLong; 104 var key_buffer: TagStatusKey = undefined; 105 const tag_set_cursor = try tag_to_issues.putCursor(try tagStatusKey(&key_buffer, tag, event.status)); 106 const tag_set = try DB.SortedSet(.read_write).init(tag_set_cursor); 107 try tag_set.put(&order_key); 108 } 109 } else { 110 // drop it from the ordered sets using its recorded creation timestamp and status 111 if (try event_id_to_issue.getCursor(issue_key)) |existing_cursor| { 112 const existing_issue = try DB.HashMap(.read_only).init(existing_cursor); 113 const existing_event = try evt.read(@This(), DB, hash_kind, arena, existing_issue); 114 const order_key = evt.orderKey(existing_event.created_ts, event_id); 115 116 const status_set = try statusSet(DB, status_to_issues, existing_event.status); 117 _ = try status_set.remove(&order_key); 118 119 try removeFromTagSets(DB, tag_to_issues, existing_event.tags, existing_event.status, &order_key); 120 } 121 if (!try event_id_to_issue.remove(issue_key)) return error.EventNotFound; 122 } 123 } 124 125 // `status`'s sorted set within `statuses`, keyed by status name 126 fn statusSet( 127 comptime DB: type, 128 statuses: DB.SortedMap(.read_write), 129 status: Status, 130 ) !DB.SortedSet(.read_write) { 131 const cursor = try statuses.putCursor(@tagName(status)); 132 return DB.SortedSet(.read_write).init(cursor); 133 } 134 135 // remove an issue's order key from its tags' `status` sets, pruning entries 136 // whose set becomes empty 137 fn removeFromTagSets( 138 comptime DB: type, 139 tag_to_issues: DB.SortedMap(.read_write), 140 tags: []const u8, 141 status: Status, 142 order_key: []const u8, 143 ) !void { 144 var tag_iter = tagIterator(tags); 145 while (tag_iter.next()) |tag| { 146 if (tag.len == 0) continue; 147 var key_buffer: TagStatusKey = undefined; 148 const key = try tagStatusKey(&key_buffer, tag, status); 149 const tag_set_cursor = try tag_to_issues.putCursor(key); 150 const tag_set = try DB.SortedSet(.read_write).init(tag_set_cursor); 151 _ = try tag_set.remove(order_key); 152 if (0 == try tag_set.count()) _ = try tag_to_issues.remove(key); 153 } 154 } 155