Skip to content

Releases: purescript-contrib/purescript-aff

v4.1.1

18 Apr 03:35
3457df9
Compare
Choose a tag to compare
  • Fixes bhead is not a function FFI errors when yielding a fork at the tail of a fresh attempt context (possibly through bracket acquisition or catchError).

v4.1.0

06 Apr 21:16
Compare
Choose a tag to compare

v4.0.2

14 Jan 18:52
22a3ad8
Compare
Choose a tag to compare
  • Fix regression in ParAff Applicative behavior when an exception occurs.

v4.0.1

19 Nov 00:09
a048d9c
Compare
Choose a tag to compare
  • Fixes JavaScript runtime error in ParAff cancellation.

v4.0.0

14 Sep 18:47
Compare
Choose a tag to compare

This release (v4.0.0) features a revamped API for writing more expressive asynchronous programs with stronger guarantees.

  • Fiber cooperative multi-tasking primitive for fork/join workflows.
  • Stronger cleanup guarantees with bracket and supervise.
  • Reformulated AVar semantics
  • Rewritten core with an emphasis on performance and consistency.

New Features and Enhancements

Fiber

Previously, Affs supported forkAff, but it was very difficult to get values back when forked computations completed. Libraries like purescript-aff-future were written to overcome this limitation (though with limitations of their own). The semantics of purescript-aff-future have been assimilated into Aff through the Fiber type without any of the previous limitaions (like lack of cancellation). Fibers make it easy to not only fork computations, but also share their results among many consumers with joinFiber, which will wait until the Fiber completes, or yield immediately if it has already resolved. If a Fiber threw an exception, then the exception will be rethrown in the observer. Fibers additionally support cancellation (killFiber) and finalizers for cleanup (bracket).

bracket

When we kill/cancel a Fiber, often times we need to make sure some resource gets released. bracket lets you take control of the acquire/use/release resource cycle.

example =
  bracket
    (openFile myFile) -- Acquire a resource
    (\file -> closeFile file) -- Release the resource
    (\file -> appendFile "hello" file) -- Use the resource

In the example above, the runtime will always ensure the "release" effect will run even in the presence of cancellation. There is also generalBracket, which lets you observe whether the primary action completed successfully, threw an exception, or was killed asynchronously and run different cleanup effects accordingly.

supervise

Sometimes we need to fork many Fibers for a task, but it's possible (often through cancellation) for these sub-tasks to leak. We've introduced a supervise combinator which will automatically keep track of forked Fibers and clean them up and run their finalizers once the computation completes or is cancelled.

example = supervise do
  _ <- forkAff requestA
  _ <- forkAff requestB
  requestC

In the above example, if requestA or requestB are still running when requestC completes, they will be killed by the runtime and have their finalizers run.

suspendAff

As an alternative to forkAff, which eagerly forks and runs a computations, we've introduced suspendAff. This forks a computation but does not initiate it until a result is demanded via joinFiber. Results are still memoized (as all Fiber results are), but are just computed lazily.

Stack-safety

With the old callback approach, each bind resulted in more and more stack, and it was trivial to blow the stack unless you explicitly used tailRecM. The Aff interpreter now uses a constant amount of stack space, making tailRecM unnecesary. This extends to ParAff as well.

Uncaught exceptions

Previously, exceptions thrown in forked computations were completely swallowed. This made it extremely difficult to diagnose bugs. Now if a Fiber has no observers and it throws an exception, the exception will always be rethrown in a fresh stack. This can be observed by things like window.onerror or just by watching the console.

Breaking Changes

  • The low-level callback representation is no longer relevant. If you've defined Aff effects via the FFI, you should transition to using Control.Monad.Aff.Compat, which provides an EffFn adapter. This makes it easy to use idiomatic JavaScript callbacks when building Aff actions.
  • The AVar API methods have changed to match Haskell's MVar API. putVar now blocks until the AVar actually assimilates the value. Previously, putVar would queue the value, but yield immediately. It's possible to recover similar behavior as the old API with forkAff (try (putVar value avar)) (though this should be considered mildly unsafe), or you can use tryPutVar which will attempt a synchronous put.
  • Argument order for AVar and Fiber operations consistently put the subject last.
  • Several unlawful instances where removed for Aff (Alternative, MonadPlus, and MonadZero).
  • forkAff now returns a Fiber rather than a Canceler.
  • forkAll was removed. Just use Traversable and forkAff directly.
  • cancel was removed. Use killFiber.
  • The signature of makeAff has changed to provide a single callback which takes an Either Error a argument. Cancelers are also required. If you are sure you have no means of cancelling an action, you can use nonCanceler or mempty.
  • Cancelers no longer yield Boolean. This was meaningless and not useful, so all cancellation effects now yield Unit.
  • ParAff is no longer a newtype. Parallel computations should be constructed via Control.Parallel with parallel and sequential.

v4.0.0-rc.6

12 Sep 22:52
Compare
Choose a tag to compare
v4.0.0-rc.6 Pre-release
Pre-release
  • Rename atomically to invincible.
  • Killing a suspended fiber should be synchronous.

v4.0.0-rc.5

31 Aug 23:14
Compare
Choose a tag to compare
v4.0.0-rc.5 Pre-release
Pre-release
  • Changed the argument order of AVar operations to have the AVar last.

v4.0.0-rc.4

26 Aug 18:18
Compare
Choose a tag to compare
v4.0.0-rc.4 Pre-release
Pre-release
  • Reexport things in Control.Monad.Eff.Exception relevant to the Aff API.

v4.0.0-rc.3

24 Aug 03:15
Compare
Choose a tag to compare
v4.0.0-rc.3 Pre-release
Pre-release
  • kill always succeeds. If a finalizer throws, it will rethrow in a fresh stack.
  • Fixes the behavior of throwError and generalBracket within a finalizer.

v4.0.0-rc.2

20 Aug 14:34
Compare
Choose a tag to compare
v4.0.0-rc.2 Pre-release
Pre-release
  • Fixes ParAff Alt behavior when propagating exceptions.