(after: number | "tail" = 0)
| 172 | // empty iterator; live tail follow happens on the live stream, |
| 173 | // not on the log. |
| 174 | *replay(after: number | "tail" = 0): IterableIterator<ExecEvent> { |
| 175 | const meta = this.meta(); |
| 176 | if (meta === undefined) { |
| 177 | throw new ExecError("ENOENT", `no exec record for id ${this.id}`); |
| 178 | } |
| 179 | if (meta.evicted === 1) { |
| 180 | throw new ExecError("ELOG_TRUNCATED", `log for exec ${this.id} has been evicted`); |
| 181 | } |
| 182 | if (after === "tail") return; |
| 183 | const rows = this.db.all<EventRow>( |
| 184 | `SELECT seq, kind, value FROM computerd_exec_log |
| 185 | WHERE exec_id = ? AND seq > ? |
| 186 | ORDER BY seq`, |
| 187 | this.id, |
| 188 | after, |
| 189 | ); |
| 190 | for (const row of rows) { |
| 191 | yield materialise(this.id, row); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | private meta(): MetaRow | undefined { |
| 196 | return this.db.one<MetaRow>(`SELECT * FROM computerd_exec_meta WHERE exec_id = ?`, this.id); |
no test coverage detected