-func (l *Log) load(ctx context.Context) error {
- return readLines(ctx, l.journal.dir, func(message Message) error {
- if message.ID != len(l.messages) {
- return fmt.Errorf("expected message %d, found %d", len(l.messages), message.ID)
+// Close releases the lock. The log refuses all calls after Close.
+func (l *Log) Close() error {
+ err := l.journal.Close()
+ if l.index != nil {
+ err = errors.Join(err, l.index.Close())
+ l.index = nil
+ }
+
+ if l.lock != nil {
+ err = errors.Join(err, l.lock.Close())
+ l.lock = nil
+ }
+
+ return err
+}
+
+// catchUp indexes the lines after the last indexed line.
+func (l *Log) catchUp(ctx context.Context) error {
+ start := Position{}
+ if l.index.count > 0 {
+ record, _, err := l.index.Read(l.index.count - 1)
+ if err != nil {
+ return fmt.Errorf("read last log position: %w", err)
+ }
+
+ last := decodePosition(record)
+ start = Position{
+ day: last.day,
+ offset: last.offset + uint64(last.length),
+ }
+ }
+
+ err := l.journal.Scan(ctx, start, func(line []byte, place Position) error {
+ var message Message
+
+ err := json.Unmarshal(line, &message)
+ if err != nil {
+ return fmt.Errorf("decode log message: %w", err)
+ }
+
+ if message.ID != l.index.count {
+ return fmt.Errorf("expected message %d, found %d", l.index.count, message.ID)