8000 GitHub - postpostscript/reactive_state: A simple Elixir library for creating and managing reactive state through GenServer processes
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

A simple Elixir library for creating and managing reactive state through GenServer processes

License

Notifications You must be signed in to change notification settings

postpostscript/reactive_state

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reactive State - Elixir

Elixir library to manage reactive state by using GenServer processes to manage each piece of state and its relationships to other reactive processes

Warning

This library is a work in progress and is not production ready.

Installation

The package can be installed by adding reactive_state to your list of dependencies in mix.exs:

def deps do
  [
    {:reactive_state, "~> 0.2.4"}
  ]
end

Documentation

Full API Documentation can be found on HexDocs

Examples

Reactive Block

To automatically import the reactive/1 and reactive/2 macros, you can use use Reactive which is the equivalent of:

import Reactive, only: [reactive: 1, reactive: 2]
alias Reactive.Ref

Example usage:

use Reactive
ref = reactive(do: 2)
ref_squared = reactive do
  get(ref) ** 2
end
Reactive.get(ref_squared)
# 4
Ref.set(ref, 3)
Reactive.get(ref_squared)
# 9

To set options at the module level, you can pass options, for example:

defmodule ReactiveExample do
  use Reactive, reactive: :reactive_protected, ref: :ref_protected, opts: [gc: false]

  def run do
    value = ref_protected(0)
    computed = reactive_protected do
      get(value) + 1
    end
    {Ref.get(value), Ref.get(computed)}
  end
end

ReactiveExample.run()
# {0, 1}

Working with data directly with Reactive.Ref

alias Reactive.Ref
ref = Ref.new(0) #PID<0.204.0>
Ref.get(ref) # or Ref.get(ref)
# 0
Ref.set(ref, 1)
# :ok
Ref.get(ref)
# 1

Supervisor

By default, new reactive processes will be linked to the current process. To override this behavior, pass the supervisor keyword arg with the name of your DynamicSupervisor during process creation:

value = Ref.new(0, supervisor: MyApp.Supervisor)
computed = reactive supervisor: MyApp.Supervisor do
  get(value) + 1
end

You can also pass default options like this:

use Reactive, ref: :ref, opts: [supervisor: MyApp.Supervisor]
...
value = ref(0)
computed = reactive do
  get(value) + 1
end

Process Restarting

If a reactive process has been killed for any reason, it will be restarted upon a Reactive.get or Ref.get call:

use Reactive
Reactive.Supervisor.ensure_started()
ref = Ref.new(0)
DynamicSupervisor.terminate_child(Reactive.Supervisor, ref)
Ref.get(ref)
# 0

Garbage Collection

The default garbage collection strategy is to kill any processes that were not accessed through a Reactive.get or Ref.get call between GC calls:

Reactive.Supervisor.ensure_started()
ref = Ref.new(0)
Reactive.Supervisor.gc()
nil == Reactive.resolve_process(ref)

Reactive processes can be protected with the gc option:

use Reactive
Reactive.Supervisor.ensure_started()

ref = Ref.new(0, gc: false)
Reactive.Supervisor.gc()
^ref = Reactive.resolve_process(ref)

ref = reactive gc: false do
   # some expensive computation
end
Reactive.Supervisor.gc()
^ref = Reactive.resolve_process(ref)

Proactive Process

Proactive reactive processes will not trigger immediately after a dependency changes; they must triggered with a call to Reactive.Supervisor.trigger_proactive

use Reactive
Reactive.Supervisor.ensure_started()

num = Ref.new(0)
ref =
  reactive proactive: true do
    get(num) + 1
  end

Reactive.get_cached(ref)
# 1

Ref.set(num, 1)
Reactive.Supervisor.trigger_proactive()
Reactive.get_cached(ref)
# 2

About

A simple Elixir library for creating and managing reactive state through GenServer processes

Topics

Resources

License

Stars

Watchers

Forks

Languages

0