~ihabunek/triglav

ref: 21a975ebecced57c7e61965ea7aca87fc78e503d triglav/lib/triglav/schemas/error.ex -rw-r--r-- 5.0 KiB
21a975ebIvan Habunek Make a deployment script 9 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
defmodule Triglav.Schemas.Error do
  use Ecto.Schema
  import Ecto.Changeset

  alias Triglav.Schemas.Zet.Route
  alias Triglav.Schemas.Osmosis.Relation

  @type t :: %__MODULE__{}

  schema "errors" do
    belongs_to :route, Route, type: :string
    belongs_to :relation, Relation
    field :key, :string
    field :params, :map, default: %{}
    field :created_at, :utc_datetime
    field :resolved_at, :utc_datetime
  end

  @spec changeset(t(), map()) :: Ecto.Changeset.t()
  def changeset(%__MODULE__{} = error, params) do
    error
    |> cast(params, [:route_id, :relation_id, :key, :params, :created_at, :resolved_at])
    |> validate_required([:route_id, :key, :params, :created_at])
  end

  @doc """
  For a given error returns a map of fields which describe the error, without
  the metadata (primary key, timestamps). This map can be used to compare two
  errors to see if they are the same.

  Map keys in `params` are strings when fetched from the db, so they are
  converted to atoms so they can be compared with errors created by factory
  methods below which use atom keys.
  """
  @spec signature(Error.t()) :: map()
  def signature(%__MODULE__{} = error) do
    error
    |> Map.take([:route_id, :relation_id, :key, :params])
    |> Map.update!(:params, &keys_to_atoms/1)
  end

  # Map keys are strings when fetched from the db, convert them to atoms
  defp keys_to_atoms(%{} = map) do
    for {k, v} <- map, into: %{} do
      k =
        cond do
          is_binary(k) -> String.to_existing_atom(k)
          is_atom(k) -> k
        end

      v =
        cond do
          is_map(v) -> keys_to_atoms(v)
          true -> v
        end

      {k, v}
    end
  end

  @spec missing_route_master(Route.t()) :: Error.t()
  def missing_route_master(%Route{} = route),
    do: %__MODULE__{key: "missing_route_master", route_id: route.id}

  @spec multiple_route_masters(Route.t()) :: Error.t()
  def multiple_route_masters(%Route{} = route),
    do: %__MODULE__{key: "multiple_route_masters", route_id: route.id}

  @spec no_relations(Route.t()) :: Error.t()
  def no_relations(%Route{} = route),
    do: %__MODULE__{key: "no_relations", route_id: route.id}

  @spec relation_not_contained_in_route_master(Route.t(), Relation.t()) :: Error.t()
  def relation_not_contained_in_route_master(%Route{} = route, %Relation{} = relation),
    do: %__MODULE__{
      key: "relation_not_contained_in_route_master",
      route_id: route.id,
      relation_id: relation.id
    }

  @spec unexpected_route_master_member_relation(Route.t(), Relation.t()) :: Error.t()
  def unexpected_route_master_member_relation(%Route{} = route, relation_id),
    do: %__MODULE__{
      key: "unexpected_route_master_member_relation",
      route_id: route.id,
      relation_id: relation_id
    }

  @spec relation_not_updated_to_ptv2(Route.t(), Relation.t()) :: Error.t()
  def relation_not_updated_to_ptv2(%Route{} = route, %Relation{} = relation),
    do: %__MODULE__{
      key: "relation_not_updated_to_ptv2",
      route_id: route.id,
      relation_id: relation.id
    }

  @spec invalid_relation_name(Route.t(), Relation.t(), String.t(), String.t()) :: Error.t()
  def invalid_relation_name(%Route{} = route, %Relation{} = relation, actual, expected),
    do: %__MODULE__{
      key: "invalid_relation_name",
      route_id: route.id,
      relation_id: relation.id,
      params: %{expected: expected, actual: actual}
    }

  @spec relation_missing_required_tags(Route.t(), Relation.t(), [String.t()]) :: Error.t()
  def relation_missing_required_tags(%Route{} = route, %Relation{} = relation, tags),
    do: %__MODULE__{
      key: "relation_missing_required_tags",
      route_id: route.id,
      relation_id: relation.id,
      params: %{tags: tags}
    }

  @spec relation_contains_unexpected_tags(Route.t(), Relation.t(), [String.t()]) :: Error.t()
  def relation_contains_unexpected_tags(%Route{} = route, %Relation{} = relation, tags),
    do: %__MODULE__{
      key: "relation_contains_unexpected_tags",
      route_id: route.id,
      relation_id: relation.id,
      params: %{tags: tags}
    }

  @spec relation_missing_gtfs_stop_ids(Route.t(), Relation.t(), integer()) :: Error.t()
  def relation_missing_gtfs_stop_ids(%Route{} = route, %Relation{} = relation, count),
    do: %__MODULE__{
      key: "relation_missing_gtfs_stop_ids",
      route_id: route.id,
      relation_id: relation.id,
      params: %{count: count}
    }

  @spec invalid_tag_value(Route.t(), Relation.t(), String.t(), String.t(), String.t()) ::
          Error.t()
  def invalid_tag_value(%Route{} = route, %Relation{} = relation, name, actual, expected),
    do: %__MODULE__{
      key: "invalid_tag_value",
      route_id: route.id,
      relation_id: relation.id,
      params: %{name: name, expected: expected, actual: actual}
    }

  @spec broken_route(Route.t(), Relation.t(), integer()) :: Error.t()
  def broken_route(%Route{} = route, %Relation{} = relation, way_id),
    do: %__MODULE__{
      key: "broken_route",
      route_id: route.id,
      relation_id: relation.id,
      params: %{way_id: way_id}
    }
end