jackfirth / racket-disposable

An experimental Racket library providing an abstraction for values associated with external resources that allows automatic resource pooling, per-thread virtual construction, and monadic composition
Apache License 2.0
7 stars 0 forks source link

Timeout-guarded reusable disposables #9

Closed jackfirth closed 7 years ago

jackfirth commented 7 years ago

The http package keeps connections alive for a configurable amount of time after they're disconnected, reusing them if they're asked for within that amount of time. This is a lighter-weight alternative to pools, which are designed for resources that are thread-specific. The timeout strategy essentially converts a disposable value into a disposable value that will yield the same value if used in quick succession. That could be achieved with something like this:

(define reusable (timeout-disposable (some-disposable) #:timeout 1000)
(with-disposable ([v reusable]) ;; a fresh value
  do some stuff...)
(with-disposable ([v reusable]) ;; a reused value
  do some stuff...)
(sleep 2) ;; causes the timeout to trigger
(with-disposable ([v reusable]) ;; a fresh value
  do some stuff...)

The returned disposable constructs an alarm-evt upon disposal that waits 1 second before actually disposing the value. If the disposable is used again in that timeframe, the previous value is reused. This can be generalized by replace #:timeout with a thunk that produces an event to synchronize on after attempted disposable, but I'm not sure what the use cases are for that yet.

jackfirth commented 7 years ago

I think I got this wrong, and this should use a pool of disposables under the hood. The http package doesn't reuse a connection concurrently between threads, so it combines the timeout strategy here with a pool. Instead, I think timeout-disposable should take a (disposable/c (pool/c A)) and convert it to a (disposable/c A), hiding the pool with timeout logic. By removing all values from the pool after a timeout, it's not possible for the pool to be a source of leaked resources, making it safe to not expose the pool itself as a disposable.

jackfirth commented 7 years ago

I don't think this works properly with pools. Instead, timeout logic for pools should be integrated with keyword arguments like this:

(disposable-pool disp

  ;; no more than ten values available for reuse at any time
  #:max-idle 10

  ;; there should be at least one value ready for new clients at any time
  #:min-idle 1

  ;; idle values are removed from the pool after 1 second of inactivity
  ;; values may be kept anyway to satisfiy #:min-idle
  #:expire-after 1000)
jackfirth commented 7 years ago

Closing in favor of #16