From c52600850b514a5bc04124aa3af6909c96f05849 Mon Sep 17 00:00:00 2001 From: Amos L King Date: Thu, 2 Sep 2021 10:26:26 -0500 Subject: [PATCH] Adds `Deadline.time_exceeded\1` I often find myself wanting to get the time that we have blown past the deadline for logging, debugging, or generally gathering more information about the response times of down stream services. Since we are using Deadline for ensuring that we don't continue to wait around I often find myself pulling the deadline time out of the context and then copying how `Deadline.time_remaining\1` works, b ut swapping the subtraction. It would nice to be able to not have to worry about the internal workings of Deadline and get the information straight from Deadline. --- lib/deadline.ex | 15 +++++++++++++++ test/deadline_test.exs | 26 ++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/deadline.ex b/lib/deadline.ex index 359391b..b5380fc 100644 --- a/lib/deadline.ex +++ b/lib/deadline.ex @@ -64,6 +64,21 @@ defmodule Deadline do end end + @doc """ + Returns the time past the deadline, in a given unit. Defaults to `:millisecond` units. + If the deadline has not been exceeded then the time exceeded will be 0. + If there is no deadline then the time exceeded will be nil. + """ + def time_exceeded(unit \\ :millisecond) do + case Process.get(@key) do + nil -> + nil + + ctx -> + max(0, to_unit(unit, current_time() - ctx.deadline)) + end + end + @doc """ Checks if a deadline has been reached or exceeded. """ diff --git a/test/deadline_test.exs b/test/deadline_test.exs index 327bf9d..248095f 100644 --- a/test/deadline_test.exs +++ b/test/deadline_test.exs @@ -92,8 +92,25 @@ defmodule DeadlineTest do assert 0 < new_remaining && new_remaining < remaining end - test "time_remaining/1 returns infinity if there is no deadline set" do - assert Deadline.time_remaining == :infinity + test "time_remaining/1 returns :infinity if there is no deadline set" do + assert Deadline.time_remaining() == :infinity + end + + test "time_exceeded/1 returns 0 if the deadline has not been reached" do + Deadline.set(5_000) + exceeded = Deadline.time_exceeded() + assert 0 == exceeded + end + + test "time_exceeded/1 returns nil if there is not context" do + assert Deadline.time_exceeded() == nil + end + + test "time_exceeded/1 returns the time past the deadline when the deadline is exceeded" do + Deadline.set(10) + Process.sleep(20) + exceeded = Deadline.time_exceeded() + assert exceeded > 0 end test "can determine if a deadline has been reached" do @@ -109,8 +126,9 @@ defmodule DeadlineTest do test "doesn't explode if there is no deadline context set" do ctx = Deadline.get() assert Deadline.set(ctx) == nil - assert Deadline.time_remaining == :infinity - assert Deadline.reached? == false + assert Deadline.time_remaining() == :infinity + assert Deadline.time_exceeded() == nil + assert Deadline.reached?() == false end test "time_remaining/1 always returns 0 if the deadline has been exceeded" do