+ return Position{}, fmt.Errorf("open day file: %w", err)
+ }
+
+ info, err := j.file.Stat()
+ if err != nil {
+ return Position{}, fmt.Errorf("read day file size: %w", err)
+ }
+
+ j.day = number
+ j.size = uint64(info.Size())
+ }
+
+ _, err = j.file.Write(line)
+ if err != nil {
+ return Position{}, fmt.Errorf("write line: %w", err)
+ }
+
+ place := Position{
+ day: number,
+ offset: j.size,
+ length: uint32(len(line)),
+ }
+ j.size += uint64(len(line))
+
+ return place, nil
+}
+
+// Read returns the line at place without its newline.
+func (j *Journal) Read(place Position) ([]byte, error) {
+ reader, open := j.readers[place.day]
+ if !open {
+ var err error
+ reader, err = os.Open(filepath.Join(j.dir, journalDayName(place.day)+".jsonl"))
+ if err != nil {
+ return nil, fmt.Errorf("open day file: %w", err)