Skip to content

Commit

Permalink
Added enum type for survey state (#2079)
Browse files Browse the repository at this point in the history
* Added enum type for survey state
  • Loading branch information
leandroradusky authored May 16, 2022
1 parent 6428290 commit ff65c40
Show file tree
Hide file tree
Showing 39 changed files with 334 additions and 324 deletions.
12 changes: 6 additions & 6 deletions lib/ask/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ defmodule Ask.Channel do
end

# Deletes a channel and:
# - marks related "ready" surveys as "not_ready"
# - marks related "running" surveys as "terminated" with exit code 3
# - marks related :ready surveys as :not_ready
# - marks related :running surveys as :terminated with exit code 3
def delete(channel) do
surveys =
Repo.all(
Expand All @@ -64,17 +64,17 @@ defmodule Ask.Channel do

Enum.each(surveys, fn survey ->
case survey.state do
"ready" ->
:ready ->
survey
|> Ask.Survey.changeset(%{state: "not_ready"})
|> Ask.Survey.changeset(%{state: :not_ready})
|> Repo.update!()

"running" ->
:running ->
Ask.Survey.cancel_respondents(survey)

survey
|> Ask.Survey.changeset(%{
state: "terminated",
state: :terminated,
exit_code: 3,
exit_message: "Channel '#{channel.name}' no longer exists"
})
Expand Down
4 changes: 2 additions & 2 deletions lib/ask/floip_pusher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule Ask.FloipPusher do
from endpoint in FloipEndpoint,
join: survey in Survey,
on: endpoint.survey_id == survey.id,
where: survey.state == "running" or survey.state == "terminated",
where: survey.state == :running or survey.state == :terminated,
where: endpoint.retries < 10,
where: endpoint.state == "enabled",
order_by: endpoint.survey_id
Expand Down Expand Up @@ -78,7 +78,7 @@ defmodule Ask.FloipPusher do
)
end
else
if endpoint.survey.state == "terminated" do
if endpoint.survey.state == :terminated do
endpoint_change = Ecto.Changeset.change(endpoint, state: "terminated")
Repo.update!(endpoint_change)

Expand Down
2 changes: 1 addition & 1 deletion lib/ask/runtime/broker.ex
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ defmodule Ask.Runtime.Broker do
all_running_surveys =
Repo.all(
from(s in Survey,
where: s.state == "running",
where: s.state == :running,
preload: [respondent_groups: [respondent_group_channels: :channel]]
)
)
Expand Down
4 changes: 2 additions & 2 deletions lib/ask/runtime/panel_survey.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule Ask.Runtime.PanelSurvey do
name: PanelSurvey.new_wave_name(),
description: survey.description,
mode: survey.mode,
state: "ready",
state: :ready,
started_at: Timex.now(),
panel_survey_id: survey.panel_survey_id
}
Expand Down Expand Up @@ -72,7 +72,7 @@ defmodule Ask.Runtime.PanelSurvey do
def create_panel_survey_from_survey(%{
state: state
})
when state != "ready",
when state != :ready,
do: {
:error,
"Survey must be ready to launch to generate a panel survey"
Expand Down
2 changes: 1 addition & 1 deletion lib/ask/runtime/questionnaire_simulator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ defmodule Ask.Runtime.QuestionnaireSimulator do
project_id: project.id,
name: questionnaire.name,
mode: [[mode]],
state: "running",
state: :running,
cutoff: 1,
schedule: Ask.Schedule.always(),
started_at: Timex.now()
Expand Down
8 changes: 4 additions & 4 deletions lib/ask/runtime/survey_action.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule Ask.Runtime.SurveyAction do
|> Repo.preload([:questionnaires])
|> Repo.preload(respondent_groups: :channels)

if survey.state == "ready" do
if survey.state == :ready do
channels =
survey.respondent_groups
|> Enum.flat_map(& &1.channels)
Expand Down Expand Up @@ -68,7 +68,7 @@ defmodule Ask.Runtime.SurveyAction do
survey = Repo.preload(survey, [:quota_buckets, :project])

case [survey.state, survey.locked] do
["terminated", false] ->
[:terminated, false] ->
# Cancelling a cancelled survey is idempotent.
# We must not error, because this can happen if a user has the survey
# UI open with the cancel button, and meanwhile the survey is cancelled
Expand All @@ -78,7 +78,7 @@ defmodule Ask.Runtime.SurveyAction do
# UI open with the cancel button, and meanwhile the survey finished
{:ok, %{survey: survey}}

["running", false] ->
[:running, false] ->
changeset =
Survey.changeset(survey, %{
state: "cancelling",
Expand Down Expand Up @@ -117,7 +117,7 @@ defmodule Ask.Runtime.SurveyAction do
defp perform_start(survey) do
changeset =
Survey.changeset(survey, %{
state: "running",
state: :running,
started_at: SystemTime.time().now,
last_window_ends_at: Schedule.last_window_ends_at(survey.schedule)
})
Expand Down
46 changes: 28 additions & 18 deletions lib/ask/survey.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,17 @@ defmodule Ask.Survey do
# * 2nd mode sequence: SMS as primary mode, no fallback mode
field :mode, JSON
# not_ready, ready, pending, running, terminated, cancelling
field :state, :string, default: "not_ready"
field :state, Ecto.Enum,
values: [
:not_ready,
:ready,
:pending,
:running,
:terminated,
:cancelling
],
default: :not_ready

field :locked, :boolean, default: false
field :exit_code, :integer
field :exit_message, :string
Expand All @@ -59,9 +69,9 @@ defmodule Ask.Survey do
field :cutoff, :integer
field :count_partial_results, :boolean, default: false
field :schedule, Schedule, default: Schedule.default()
# The moment when the survey changes to %{state: "running"} and the moment when the survey
# The moment when the survey changes to %{state: :running} and the moment when the survey
# becomes actually active may differ because of its schedule configuration.
# started_at: the moment when the survey change to %{state: "running"}.
# started_at: the moment when the survey change to %{state: :running}.
field :started_at, :utc_datetime

# first_window_started_at: the moment when the survey becomes actually active for the first time.
Expand Down Expand Up @@ -166,7 +176,7 @@ defmodule Ask.Survey do
end

defp set_ended_at_in_terminated_survey(changeset) do
if get_field(changeset, :state) == "terminated" do
if get_field(changeset, :state) == :terminated do
change(changeset, ended_at: SystemTime.time().now |> DateTime.truncate(:second))
else
changeset
Expand Down Expand Up @@ -207,19 +217,19 @@ defmodule Ask.Survey do
state = get_field(changeset, :state)

cond do
state == "not_ready" && ready ->
change(changeset, state: "ready")
state == :not_ready && ready ->
change(changeset, state: :ready)

state == "ready" && !ready ->
change(changeset, state: "not_ready")
state == :ready && !ready ->
change(changeset, state: :not_ready)

true ->
changeset
end
end

def editable?(%{state: "running"}), do: false
def editable?(%{state: "terminated"}), do: false
def editable?(%{state: :running}), do: false
def editable?(%{state: :terminated}), do: false
def editable?(_), do: true

def validate_from_less_than_to(changeset) do
Expand Down Expand Up @@ -426,7 +436,7 @@ defmodule Ask.Survey do
do: ConfigHelper.get_config(Ask.Runtime.Broker, name, &String.to_integer/1)

def launched?(survey) do
survey.state in ["running", "terminated"]
survey.state in [:running, :terminated]
end

def adjust_timezone(date_time, %Survey{} = survey) do
Expand All @@ -442,20 +452,20 @@ defmodule Ask.Survey do
end

def completed?(survey) do
survey.state == "terminated" && survey.exit_code == 0
survey.state == :terminated && survey.exit_code == 0
end

def cancelled?(survey) do
survey.state == "terminated" && survey.exit_code == 1
survey.state == :terminated && survey.exit_code == 1
end

def has_floip_package?(survey) do
survey.state == "running" || survey.state == "terminated"
survey.state == :running || survey.state == :terminated
end

def cancel_respondents(survey) do
from(r in Respondent, where: r.state == :active and r.survey_id == ^survey.id)
|> Repo.update_all(set: [state: "cancelled", session: nil, timeout_at: nil])
|> Repo.update_all(set: [state: :cancelled, session: nil, timeout_at: nil])
end

def with_links(%Survey{} = survey, level \\ "owner") do
Expand Down Expand Up @@ -490,7 +500,7 @@ defmodule Ask.Survey do
def running_channels() do
query =
from s in Survey,
where: s.state == "running",
where: s.state == :running,
join: group in RespondentGroup,
on: s.id == group.survey_id,
join: rgc in RespondentGroupChannel,
Expand Down Expand Up @@ -742,7 +752,7 @@ defmodule Ask.Survey do
end)
end

def terminated?(survey), do: survey.state == "terminated"
def terminated?(survey), do: survey.state == :terminated

def succeeded?(survey), do: terminated?(survey) and survey.exit_code == 0

Expand Down Expand Up @@ -805,7 +815,7 @@ defmodule Ask.Survey do
end

# Running surveys aren't deletable
def deletable?(%{state: "running"} = _survey), do: false
def deletable?(%{state: :running} = _survey), do: false
# Only wave of a panel survey isn't deletable (because a panel survey cannot be empty)
def deletable?(survey), do: not only_wave_of_panel_survey?(survey)

Expand Down
2 changes: 1 addition & 1 deletion lib/ask/survey_respondents_canceller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule Ask.RespondentsCancellerProducer do
query =
from(
s in Survey,
where: s.state == "cancelling",
where: s.state == :cancelling,
select: s.id
)

Expand Down
2 changes: 1 addition & 1 deletion lib/ask_web/controllers/mobile_survey_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ defmodule AskWeb.MobileSurveyController do
survey = Repo.preload(respondent, :survey).survey

cond do
survey.state == "terminated" ->
survey.state == :terminated ->
questionnaires = Repo.preload(survey, :questionnaires).questionnaires
questionnaire = Enum.random(questionnaires)

Expand Down
2 changes: 1 addition & 1 deletion lib/ask_web/controllers/project_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ defmodule AskWeb.ProjectController do
from p in Project,
join: s in Survey,
select: {p.id, count(s.id)},
where: s.project_id == p.id and s.state == "running",
where: s.project_id == p.id and s.state == :running,
group_by: p.id
)
|> Enum.into(%{})
Expand Down
2 changes: 1 addition & 1 deletion lib/ask_web/controllers/respondent_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ defmodule AskWeb.RespondentController do
percents_by_date = [{started_at |> DateTime.to_date(), 0}] ++ percents_by_date

percents_by_date =
if state == "running" do
if state == :running do
percents_by_date ++ [{DateTime.utc_now() |> DateTime.to_date(), 0}]
else
percents_by_date
Expand Down
4 changes: 2 additions & 2 deletions lib/ask_web/controllers/survey_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule AskWeb.SurveyController do
if params["state"] do
if params["state"] == "completed" do
# Same as Survey.succeeded?(s)
dynamic([s], s.state == "terminated" and s.exit_code == 0 and ^dynamic)
dynamic([s], s.state == :terminated and s.exit_code == 0 and ^dynamic)
else
dynamic([s], s.state == ^params["state"] and ^dynamic)
end
Expand Down Expand Up @@ -432,7 +432,7 @@ defmodule AskWeb.SurveyController do
|> Survey.with_links(user_level(project_id, current_user(conn).id))

case survey.state do
"running" ->
:running ->
[survey_changeset, activity_log] =
case locked do
true ->
Expand Down
2 changes: 1 addition & 1 deletion lib/ask_web/controllers/survey_simulation_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defmodule AskWeb.SurveySimulationController do
project_id: project.id,
name: questionnaire.name,
mode: [[mode]],
state: "ready",
state: :ready,
cutoff: 1,
schedule: Ask.Schedule.always()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ defmodule Ask.Repo.Migrations.SetDefaultStateForSurveys do

def up do
alter table(:surveys) do
modify :state, :string, default: "pending"
modify :state, :string, default: :pending
end

flush()

from(s in Ask.Survey, where: is_nil(s.state))
|> Ask.Repo.update_all(set: [state: "pending"])
|> Ask.Repo.update_all(set: [state: :pending])
end

def down do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ defmodule Ask.Repo.Migrations.RenameSurveyStateDefaultToNotReady do
import Ecto.Query

def up do
from(s in Ask.Survey, where: s.state == "pending")
|> Ask.Repo.update_all(set: [state: "not_ready"])
from(s in Ask.Survey, where: s.state == :pending)
|> Ask.Repo.update_all(set: [state: :not_ready])
end

def down do
from(s in Ask.Survey, where: s.state == "not_ready")
|> Ask.Repo.update_all(set: [state: "pending"])
from(s in Ask.Survey, where: s.state == :not_ready)
|> Ask.Repo.update_all(set: [state: :pending])
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ defmodule Ask.Repo.Migrations.AddExitMessageAndExitCodeToSurveys do

from(s in "surveys", where: s.state == "completed")
|> Ask.Repo.update_all(
set: [state: "terminated", exit_code: 0, exit_message: "Successfully completed"]
set: [state: :terminated, exit_code: 0, exit_message: "Successfully completed"]
)

from(s in "surveys", where: s.state == "cancelled")
|> Ask.Repo.update_all(
set: [state: "terminated", exit_code: 1, exit_message: "Cancelled by user"]
set: [state: :terminated, exit_code: 1, exit_message: "Cancelled by user"]
)
end

Expand Down
Loading

0 comments on commit ff65c40

Please sign in to comment.