• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

camatcode / basenji / 81b6c37c77d8ae82554fa9f03e976087d8009986

27 Jul 2025 01:38PM UTC coverage: 81.908% (+0.2%) from 81.695%
81b6c37c77d8ae82554fa9f03e976087d8009986

Pull #72

github

camatcode
perf: introduce oban telemetry
Pull Request #72: perf: introduce telemetry

76 of 86 new or added lines in 14 files covered. (88.37%)

40 existing lines in 10 files now uncovered.

1159 of 1415 relevant lines covered (81.91%)

500.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.89
/lib/basenji/reader/pdf_reader.ex
1
defmodule Basenji.Reader.PDFReader do
2
  @moduledoc false
3

4
  import Basenji.Reader
5

6
  def format, do: :pdf
2✔
7

8
  def file_extensions, do: ["pdf"]
813✔
9

10
  def get_magic_numbers, do: [%{offset: 0, magic: [0x25, 0x50, 0x44, 0x46, 0x2D]}]
811✔
11

12
  def close(_any), do: :ok
3✔
13

14
  def get_entries(pdf_file_path, _opts \\ []) do
15
    with {:ok, %{pages: pages}} <- get_metadata(pdf_file_path) do
814✔
16
      padding = String.length("#{pages}")
813✔
17

18
      file_entries =
813✔
19
        1..pages
20
        |> Enum.map(fn idx ->
21
          %{file_name: "#{String.pad_leading("#{idx}", padding, "0")}.jpg"}
3,252✔
22
        end)
23

24
      {:ok, %{entries: file_entries}}
25
    end
26
  end
27

28
  def get_entry_stream!(pdf_file_path, entry) do
29
    file_name = entry[:file_name]
45✔
30
    {page_num, _rest} = Integer.parse(file_name)
45✔
31

32
    create_resource(fn ->
45✔
33
      with {:ok, output} <- exec("pdftoppm", ["-f", "#{page_num}", "-singlefile", "-jpeg", "-q", pdf_file_path]) do
45✔
34
        [output |> :binary.bin_to_list()]
35
      end
36
    end)
37
  end
38

39
  def read(pdf_file_path, _opts \\ []) do
40
    with {:ok, %{entries: file_entries}} <- get_entries(pdf_file_path) do
812✔
41
      file_entries =
812✔
42
        file_entries
43
        |> Enum.map(fn entry ->
44
          entry
45
          |> Map.put(:stream_fun, fn -> get_entry_stream!(pdf_file_path, entry) end)
3,248✔
46
        end)
47

48
      {:ok, %{entries: file_entries}}
49
    end
50
  end
51

52
  def get_metadata(pdf_file_path) do
53
    with {:ok, output} <- exec("pdfinfo", ["-isodates", pdf_file_path]) do
814✔
54
      metadata =
813✔
55
        String.split(output, "\n")
56
        |> Map.new(fn line ->
57
          String.split(line, ":", parts: 2)
58
          |> case do
14,634✔
59
            [k, v] -> to_metadata(k, v)
14,634✔
UNCOV
60
            [v] -> to_metadata("unknown_#{System.monotonic_time()}", v)
×
61
          end
62
        end)
63

64
      {:ok, metadata}
65
    end
66
  end
67

68
  defp to_metadata(k, v) do
69
    k = k |> String.trim() |> ProperCase.snake_case() |> String.to_atom()
14,634✔
70
    v = convert_value(k, v |> String.trim())
14,634✔
71
    {k, v}
72
  end
73

74
  defp convert_value(:creation_date, v), do: DateTimeParser.parse!(v)
813✔
75
  defp convert_value(:mod_date, v), do: DateTimeParser.parse!(v)
813✔
76
  defp convert_value(:pages, v), do: String.to_integer(v)
813✔
77

78
  defp convert_value(:filesize, v) do
79
    {first, _rest} = Integer.parse(v)
813✔
80
    first
813✔
81
  end
82

83
  defp convert_value(:pagesize, v) do
84
    String.split(v, " ")
85
    |> Enum.reduce([], fn part, acc ->
86
      Integer.parse(part)
87
      |> case do
3,252✔
88
        {coord, _rest} -> [coord | acc]
1,626✔
89
        _ -> acc
1,626✔
90
      end
91
    end)
92
    |> case do
813✔
93
      [x, y] -> {x, y}
813✔
UNCOV
94
      _ -> v
×
95
    end
96
  end
97

UNCOV
98
  defp convert_value(_k, "yes"), do: true
×
99
  defp convert_value(_k, "no"), do: false
6,504✔
100
  defp convert_value(_k, "none"), do: nil
813✔
101
  defp convert_value(_k, v), do: v
3,252✔
102
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc