All Projects → vodori → reactors

vodori / reactors

Licence: MIT License
Maintain state, incorporate change, broadcast deltas. Reboot on error.

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to reactors

react-mobx-router5
React components for routing solution using router5 and mobx
Stars: ✭ 58 (+241.18%)
Mutual labels:  reactive
kit
C++11 libs: await, channels, reactive/signals, timelines, alarms, logging, args, etc.
Stars: ✭ 21 (+23.53%)
Mutual labels:  reactive
Cycle.swift
An experiment in unidirectional architecture inspired by Cycle.js. https://cycle.js.org
Stars: ✭ 24 (+41.18%)
Mutual labels:  reactive
ByteTrack
ByteTrack: Multi-Object Tracking by Associating Every Detection Box
Stars: ✭ 1,991 (+11611.76%)
Mutual labels:  real-time
transform-hub
Flexible and efficient data processing engine and an evolution of the popular Scramjet Framework based on node.js. Our Transform Hub was designed specifically for data processing and has its own unique algorithms included.
Stars: ✭ 38 (+123.53%)
Mutual labels:  real-time
percival
📝 Web-based, reactive Datalog notebooks for data analysis and visualization
Stars: ✭ 285 (+1576.47%)
Mutual labels:  reactive
eventide-postgres
Event Sourcing and Microservices Stack for Ruby
Stars: ✭ 92 (+441.18%)
Mutual labels:  reactive
TorrentsDuck
A multi users bittorrents client with a responsive web UI that quacks 🦆
Stars: ✭ 42 (+147.06%)
Mutual labels:  real-time
SiamFC-tf
A TensorFlow implementation of the SiamFC tracker, use with your own camera and video, or integrate to your own project 实时物体追踪,封装API,可整合到自己的项目中
Stars: ✭ 22 (+29.41%)
Mutual labels:  real-time
TogetherStream
A social and synchronized streaming experience
Stars: ✭ 16 (-5.88%)
Mutual labels:  real-time
platyplus
Low-code, offline-first apps with Hasura
Stars: ✭ 22 (+29.41%)
Mutual labels:  real-time
verse-blender
Blender Python Add-on with Verse integration
Stars: ✭ 36 (+111.76%)
Mutual labels:  real-time
asana-webhooks-manager
Asana Webhooks Manager (AWM) is a free and open source management and event handling server, written in JavaScript (NodeJS, Angular) for Asana's webhooks API. Use AWM to manage webhooks subscriptions and accept event payloads from Asana in real-time. Want to create your own Asana Dashboard? Consider AWM as your starting point!
Stars: ✭ 23 (+35.29%)
Mutual labels:  real-time
MetaRx
Reactive data structures for Scala and Scala.js
Stars: ✭ 36 (+111.76%)
Mutual labels:  reactive
spring-five-functional-reactive
No description or website provided.
Stars: ✭ 20 (+17.65%)
Mutual labels:  reactive
vue3-demo
💡 vue3新特性示例: 响应式API、组合式API、TodoMVC
Stars: ✭ 114 (+570.59%)
Mutual labels:  reactive
el.js
✨ Higher-order elements powered by transclusion.
Stars: ✭ 35 (+105.88%)
Mutual labels:  reactive
mute-structs
MUTE-structs is a Typescript library that provides an implementation of the LogootSplit CRDT algorithm.
Stars: ✭ 14 (-17.65%)
Mutual labels:  real-time
crypto-websocket-extensions
🧰 Unified and optimized data structures across cryptocurrency exchanges
Stars: ✭ 31 (+82.35%)
Mutual labels:  reactive
RxJava-Codelab
Codelab project for demonstration of RxJava features
Stars: ✭ 44 (+158.82%)
Mutual labels:  reactive

Build Status Maven metadata URL

Reactors

A Clojure library to provide structure around shared in-memory state, incorporating live changes, and broadcasting change deltas to observers. State is maintained using clojure agents and supports a configurable crash recovery strategy.

Rationale

Reactors provide leverage when implementing server-heavy collaborative processes by reigning in the independent sources of change and then broadcasting zero or more messages to the subscribers based on differences between the old and new state.

While you can certainly create lots of similar things yourself, reactors implements a couple of key ideas that we value:

  • A unified way to communicate state to new subscribers and existing subscribers as things change.
  • Recovery of errors that might have tainted the accumulated view of the current state.

Stability

We use reactors in a production capacity. We think the abstractions are simple but useful and so are unlikely to change.


Core Abstractions:

A reactor consists of some source of initial state (initializer), sources of change (publishers), observers of state (subscribers), a function for incorporating change (reducer), a function for describing changes in state to observers (emitter), and functions that cleanup when a reactor implodes (destroyers).

Initializer

A function of no arguments that is used to "boot" the reactor. Also used for any "reboots" after a crash. It's just a function that should return the initial state to be contained in the reactor before starting to incorporate events from publishers. This function is free to do dangerous things. If anything fails it will be retried according to the recovery strategy.

(defn initializer []
  {})

Publishers

A map of opaque identifiers to core.async channels representing sources of change. Publishers can be added to and removed from a reactor at any time.

(def publishers 
 {::database (get-database-change-stream-chan)
  ::webhooks (get-incoming-webhook-events-chan)})

Subscribers

A map of opaque identifiers to core.async channels representing observers of state. Subscribers can be added to and removed from a reactor at any time.

(def subscribers 
 {::paul (username->websocket-chan "[email protected]")
  ::eric (username->websocket-chan "[email protected]")})

Reducer

A function for incorporating change into current state. It's okay if this function does things like making database calls to gather additional information because it runs on the agent which can be restarted if it crashes. The first argument is the current state contained by the reactor and the second argument is a tuple of the publisher identity and the event itself.

(defn reducer [state [publisher event]]
  (case (:kind event)
    :insert (assoc state (:id event) (:data event))
    :delete (dissoc state (:id event))
    state))

Emitter

A function for deciding what changes in state should be broadcast to subscribers. This function receives the old state and new state (after a successful run of the reducer) and should return a sequence of messages to be broadcast to subscribers. Your emitter must be a pure function and should not make assumptions about the way in which state is known to change in your application (it should detect them instead).

(defn emitter [old-state new-state]
  (let [[added removed] (data/diff (keys new-state) (keys old-state))]
    (cond-> []
      (not-empty added) (conj {:event :added :data (mapv new-state added)})
      (not-empty removed) (conj {:event :removed :data (mapv old-state removed)})))

Destructors

Functions of no arguments that perform housekeeping after a reactor implodes. Reactors implode when they have exhausted the entire recovery strategy or when the reactor has gone from having some subscribers to having no subscribers.

(def destructors
  {::pool (fn [] (swap! reactor-pool disj reactor))})

Install

[com.vodori/reactors "0.1.0"]

Usage

; wait 10 millis to start
; double the wait every time
; only restart up to 10 times (then implode!)
(def recovery-policy
  (take 10 (iterate (partial * 2) 10)))

; create the reactor. This is a simplified example
; but in reality, it's not unusual to close over
; some unique per-reactor state inside the various 
; functions (reducer, emitter, initializer)
(def reactor 
  (-> {:reducer reducer 
       :emitter emitter 
       :backoff recovery-policy
       :initializer initializer}
       
      (reactors/create-reactor)
      
      ; you can also do this any time throughout the
      ; life of the reactor (as users come and go)
      (reactors/add-publishers publishers)
      (reactors/add-subscribers subscribers)
      (reactors/add-destructors destructors)
      
      ; start listening to events from publishers
      ; and broadcasting incorporated changes to any
      ; subscribers
      (reactors/start!)))


; inside of your functions (reducer, emitter, initializer)
; you can also access the 'current reactor'. Use the function
; (reactors/current-reactor). It will return nil if not called
; from within a reactor function.

License

This project is licensed under MIT license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].