I have an ets set table in an elixir app. I need to clean-up records which have their updated_at field older than 10 seconds. Is there a way I can set expiry or do it manually without iterating over all the records? I match records based on the timestamps greater than given time.
example record:
key: key_1
record: %{id: key_1, updated_at: ~N[2018-12-19 10:08:47.803075]}
so far I have this code
def clean_stale(previous_key) do
if previous_key == :"$end_of_table" do
:ok
else
device = get(previous_key)
next_key = :ets.next(__MODULE__, previous_key)
if NaiveDateTime.diff(NaiveDateTime.utc_now, device.last_recorded_at) > 10 do
remove(device.id)
end
clean_stale(next_key)
end
end
If you store the "updated at" time as an integer instead of as a
NaiveDateTimestruct, you can use a match spec.For example, to get the current time as the number of seconds since the Unix epoch:
You can do something like this:
In the call to
ets:select_delete/2, I pass a match specification. It consists of three parts:{:_, :"$1"}, I perform a match on the records in the table. In this example, I have a tuple with two elements. I ignore the key with:_, and assign the timestamp to a match variable with:"$1".[{:<, :"$1", 1545215144}], I specify that I only want to match records with a timestamp before this time. In your case, you would calculate the time ten seconds in the past and put that value here.[true], I specify that I want to returntruefor matching records, which in the case ofselect_deletemeans "delete this record".So after calling
select_delete, only the second record remains in the table.If the timestamp is inside a map, you can use
map_getto access it and compare it:Or (in Erlang/OTP 18.0 and later) match out the map value: