     # Copy configs
     [current, _] = repos
     copy_configs(current)
-    {:ok, %{repos: repos, needs_hard_sync: needs_hard_sync}}
-  end
-
-  defp copy_configs(repo) do
-    case repo.one(Device) do
-      nil -> :ok
-      %{timezone: tz} ->
-        ConfigStorage.update_config_value(:string, "settings", "timezone", tz)
-        :ok
-    end
-  end
-
-  def terminate(_,_) do
-    BotState.set_sync_status(:sync_error)
+    {:ok, %{repos: repos, needs_hard_sync: needs_hard_sync, timer: start_timer()}}
+  end
+
+  def terminate(reason,_) do
+    if reason not in [:normal, :shutdown] do
+      BotState.set_sync_status(:sync_error)
+    end
+  end
+
+  def handle_call(:force_hard_sync, _, state) do
+    maybe_cancel_timer(state.timer)
+    BotState.set_sync_status(:sync_now)
+    {:reply, :ok, %{state | timer: nil, needs_hard_sync: true}}
   end
 
   def handle_call(:current_repo, _, %{repos: [repo_a, _]} = state) do


  @singular_resources [Device]

  @doc "Fetch the current repo."
  def current_repo do
    GenServer.call(__MODULE__, :current_repo)

        obj.__struct__.changeset(existing, Map.from_struct(obj))
        |> repo.update()
    end
    case res do
      {:ok, _} -> res
      {:error, reason} ->
        Logger.error 2, "failed to sync #{obj.__struct__}: #{inspect reason}"
        {:error, obj.__struct__, reason}
    end
  end

