WICG / storage-buckets

API proposal for managing multiple storage buckets
https://wicg.github.io/storage-buckets/explainer
Other
44 stars 20 forks source link

Setting bucket expiration #79

Open ayuishii opened 1 year ago

ayuishii commented 1 year ago

Should expiration be set by timestamp or duration?

setExpires(Date.now() + duration_ms)

or

setMaxAge(duration_ms) or setExpiresByDuration()

While it is my personal preference to keep timestamp, there are reasons to consider duration as well. This change would also imply that with duration, the method name will be changed as well. This change could add clarity to reader's and wouldn't have to wonder if the input is by duration or timestamp.

On the other hand, there are precedents with expires as a timestamp as well. For example Cookie Store API will set expiration by timestamp. This would simply follow this familiar pattern.

Origin: https://github.com/WICG/storage-buckets/pull/62/files#r1133114171

@jyasskin @wanderview @noamr

annevk commented 1 year ago

I would much prefer setMaxAge() unless there's some compelling reason for folks to have to pass in a date of sorts.

It seems the current API already makes the mistake I pointed out in https://github.com/w3ctag/design-principles/issues/425 that it doesn't validate the input is actually in the future.

evanstade commented 1 year ago

setMaxAge() feels a little awkward to me because the original baseline timestamp is presumably the creation time, but by the time you're calling setMaxAge(), some variable amount of time has elapsed since the bucket was created. Therefore, if we wanted to switch to relative timestamps, I would name this function setTimeToExpiration() or so, where the baseline timestamp is now.

This does end up creating a slightly odd situation where the baseline time changes based on which part of the API you're looking at.

Absolute time means that all three ways of expressing this parameter will be consistent/symmetrical (e.g. setExpires(x) implies expires() will return x).

Relative time creates potential for confusion in that one could assume that the baseline time is "last use". After all, the un-spec'd storage-pressure eviction priority for buckets is set by LRU, not bucket age (in Chromium). Using expressive verbiage for the symbol names should help with this, but I can't see how that mistake could possibly be made with absolute timestamps.

I may be missing some context here which would change my assessment, but for the above reasons I would lean towards absolute times. I acknowledge the reasons enumerated on w3ctag/design-principles#425 but I don't think they're all relevant here (e.g. the argument about parsing a string representing a date) and many of the precedents don't have the same considerations listed above.

It seems the current API already makes the mistake I pointed out in https://github.com/w3ctag/design-principles/issues/425 that it doesn't validate the input is actually in the future.

Yes, this is a bug in the spec, although Chromium's implementation does enforce it correctly.

annevk commented 1 year ago

I'm not sure I fully follow. How about:

  1. Creation has a maxAge member, relative to now.
  2. expires() continues to return null or a timestamp. Though we could make this maxAge() as well and achieve full consistency.
  3. setMaxAge() is also relative to now.
ayuishii commented 1 year ago

In the case of having maxAge() would you expect this to return a timestamp or relative number? In my opinion, it seems like a timestamp would be more useful in this case, which would mean that this would be a different format from how you'd set setMaxAge(). To me, I think I'd expect having read and write to be in the same format, and expires achieves this (also commented in https://github.com/w3ctag/design-principles/issues/425#issuecomment-1679685181).

+ @asutherland curious if you have any thoughts as well!

annevk commented 1 year ago

It'd have to be a relative number as well. Why do you consider a timestamp to be more useful?

I think you make a compelling point that you want write/read consistency, but I'd imagine that if we exposed an API for when setTimeout() might run we'd return an offset as well? It's not a complete guarantee after all.

asutherland commented 1 year ago

The expiration use case as currently specified is tailored to the use case of "I have a contractual or legal obligation around this data" (see points 2 and 3 of the expiration explainer).

From my perspective this seems like an argument in favor of taking an explicit date/timestamp because that would be closest to the motivating use-case for expiration.

For semantics like "please keep this around for at least 1 week if possible, but it would be nice if it stays around longer", a relative number seems more useful, especially if the expected use-case is doing something like bucket.timeToLive = ONE_WEEK_PLEASE_MILLIS; every time we access the bucket.

ayuishii commented 1 year ago

@annevk thanks for the response!

It'd have to be a relative number as well. Why do you consider a timestamp to be more useful?

Ah I see, my thought here was that if developers wanted to pass this value around at all, like for doing their own version of LRU or showing it in the UI, it would be more reliable to have this return as a point in time so the values don't get skewed by the time between calls. I think Jeffery explained this well as his first point in favor of points in time here.

@asutherland - Thanks for your comment, that's a great distinction. I think "contractual obligation" matches how I see the expiration policy.