diff --git a/CHANGELOG.md b/CHANGELOG.md index 798b6c0..7c0a5d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- DSL-configured `shutdown_after` and `hibernate_after` options were ignored at runtime — processes never shut down even when `shutdown_after` was set in the `options` block. The values were stored for introspection but never read during process startup. `Server.init/1` and `Server.start_link/1` now fall back to the module's DSL-configured values when options are not explicitly passed. + ### Added - Built-in `state.id` field on every object's `State` struct, automatically set to the object's ID at init time diff --git a/lib/durable_object/server.ex b/lib/durable_object/server.ex index 72e02f9..d2cc573 100644 --- a/lib/durable_object/server.ex +++ b/lib/durable_object/server.ex @@ -36,7 +36,13 @@ defmodule DurableObject.Server do def start_link(opts) do module = Keyword.fetch!(opts, :module) object_id = Keyword.fetch!(opts, :object_id) - hibernate_after = Keyword.get(opts, :hibernate_after, @default_hibernate_after) + + hibernate_after = + Keyword.get_lazy(opts, :hibernate_after, fn -> + if function_exported?(module, :__durable_object__, 1), + do: module.__durable_object__(:hibernate_after), + else: @default_hibernate_after + end) GenServer.start_link(__MODULE__, opts, name: via_tuple(module, object_id), @@ -122,7 +128,13 @@ defmodule DurableObject.Server do def init(opts) do module = Keyword.fetch!(opts, :module) object_id = Keyword.fetch!(opts, :object_id) - shutdown_after = Keyword.get(opts, :shutdown_after) + + shutdown_after = + Keyword.get_lazy(opts, :shutdown_after, fn -> + if function_exported?(module, :__durable_object__, 1), + do: module.__durable_object__(:shutdown_after) + end) + repo = Keyword.get(opts, :repo) prefix = Keyword.get(opts, :prefix) default_state = module.__durable_object__(:default_state) diff --git a/test/durable_object/server_test.exs b/test/durable_object/server_test.exs index ac79c2a..940d6c1 100644 --- a/test/durable_object/server_test.exs +++ b/test/durable_object/server_test.exs @@ -237,7 +237,49 @@ defmodule DurableObject.ServerTest do end end + defmodule ShutdownHandler do + use DurableObject + + state do + field(:data, :string, default: nil) + end + + handlers do + handler(:get) + end + + options do + shutdown_after(50) + end + + def handle_get(state) do + {:reply, state, state} + end + end + describe "shutdown_after" do + test "DSL-configured shutdown_after is respected" do + id = unique_id("dsl-shutdown") + + {:ok, pid} = Server.start_link(module: ShutdownHandler, object_id: id) + + assert Process.alive?(pid) + Process.sleep(100) + refute Process.alive?(pid) + end + + test "explicit shutdown_after overrides DSL config" do + id = unique_id("dsl-shutdown-override") + + {:ok, pid} = + Server.start_link(module: ShutdownHandler, object_id: id, shutdown_after: 200) + + Process.sleep(100) + assert Process.alive?(pid) + Process.sleep(150) + refute Process.alive?(pid) + end + test "process shuts down after timeout" do {:ok, pid} = Server.start_link(