Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: extract complete_deployment into Garden.Socket.State

SOW-74

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+61 -14
+4 -14
apps/garden/lib/garden/socket.ex
··· 309 309 end 310 310 311 311 def handle_info({:deployment_completed, sid, result}, socket) do 312 - case Map.get(socket.active_deployments, sid) do 313 - nil -> 312 + case State.complete_deployment(sid, result, socket.active_deployments) do 313 + :not_found -> 314 314 Logger.warning(msg: "Deployment not found during completion", sid: sid) 315 315 {:noreply, socket} 316 316 317 - deployment -> 318 - {:ok, deployment_result} = 319 - SowerClient.Orchestration.DeploymentResult.cast(%{ 320 - request_id: deployment.request_id, 321 - deployment_sid: deployment.sid, 322 - result: result, 323 - deployed_at: DateTime.utc_now() |> DateTime.to_iso8601() 324 - }) 325 - 317 + {:ok, deployment_result, active_deployments} -> 326 318 {:ok, _result_ref} = push_message(socket, deployment_result) 327 319 328 - socket = update_in(socket.active_deployments, &Map.delete(&1, sid)) 329 - 330 320 cast(:report_seeds) 331 321 send(self(), :check_pending_reload) 332 322 333 - {:noreply, socket} 323 + {:noreply, %{socket | active_deployments: active_deployments}} 334 324 end 335 325 end 336 326
+19
apps/garden/lib/garden/socket/state.ex
··· 9 9 10 10 alias SowerClient.Orchestration.Deployment 11 11 alias SowerClient.Orchestration.DeploymentRequest 12 + alias SowerClient.Orchestration.DeploymentResult 12 13 alias SowerClient.Orchestration.Subscription 13 14 14 15 def build_seed_report( ··· 55 56 56 57 def poll_on_connect_subscriptions(subscriptions) do 57 58 Enum.filter(subscriptions, & &1.poll_on_connect) 59 + end 60 + 61 + def complete_deployment(sid, result, active_deployments) do 62 + case Map.get(active_deployments, sid) do 63 + nil -> 64 + :not_found 65 + 66 + deployment -> 67 + {:ok, deployment_result} = 68 + DeploymentResult.cast(%{ 69 + request_id: deployment.request_id, 70 + deployment_sid: deployment.sid, 71 + result: result, 72 + deployed_at: DateTime.utc_now() |> DateTime.to_iso8601() 73 + }) 74 + 75 + {:ok, deployment_result, Map.delete(active_deployments, sid)} 76 + end 58 77 end 59 78 60 79 def lookup_deployment(sid, active_deployments) do
+38
apps/garden/test/garden/socket/state_test.exs
··· 194 194 assert :not_found = State.lookup_deployment("deploy_123", %{}) 195 195 end 196 196 end 197 + 198 + describe "complete_deployment/3" do 199 + test "returns result and removes deployment from active map" do 200 + deployment = %Deployment{ 201 + sid: "deploy_123", 202 + request_id: "dr_456", 203 + seed_deployments: [], 204 + skipped: false 205 + } 206 + 207 + active = %{"deploy_123" => deployment} 208 + 209 + assert {:ok, result, updated_active} = 210 + State.complete_deployment("deploy_123", :success, active) 211 + 212 + assert result.request_id == "dr_456" 213 + assert result.deployment_sid == "deploy_123" 214 + assert result.result == :success 215 + assert result.deployed_at != nil 216 + assert updated_active == %{} 217 + end 218 + 219 + test "returns not_found when deployment missing" do 220 + assert :not_found = State.complete_deployment("deploy_123", :success, %{}) 221 + end 222 + 223 + test "preserves other deployments in map" do 224 + d1 = %Deployment{sid: "deploy_1", request_id: "dr_1", seed_deployments: [], skipped: false} 225 + d2 = %Deployment{sid: "deploy_2", request_id: "dr_2", seed_deployments: [], skipped: false} 226 + 227 + active = %{"deploy_1" => d1, "deploy_2" => d2} 228 + 229 + {:ok, _result, updated_active} = State.complete_deployment("deploy_1", :success, active) 230 + 231 + assert map_size(updated_active) == 1 232 + assert Map.has_key?(updated_active, "deploy_2") 233 + end 234 + end 197 235 end