# Hakuban

Convenient data-object sharing library.

Are you tired of handling all the little details of propagating object states? 
Computing differences, serialization, network propagation (timeouts, keep-alives, ...), somehow catching-up on reconnection, 
load balancing object production, event delivery, object lifetime control etc. **Hakuban does all of that for you.** 

For details on structs, modules, cargo feature flags, event handling, etc. head on to [documentation](https://docs.rs/hakuban/).

If you feel you may need something slightly different, there is a list of similar projects at the end of this document.

## Features
Some of Hakuban's features and properties:
- Only the difference is propagated over the network when an object changes. Compressed by default.
- Automatically handles re-synchronization on connection loss and regain.
- Object identifiers are "rich" (json), not just strings. So, for example, complex user-defined search filter on a web page, expressed as json, can directly act as an identifier of the object holding results of that search.
- Object can belong to zero or more tags, which function as wildcards for exposing or observing unknown objects.
- Supports tree network topology, with leafs happily unaware of anything not relevant to them.
- Exchanges on all levels can observe and expose alike, unlike in most database/graphql-centric solutions.
- At most one exposer is selected for each object to keep it up to date. With load balancing.
- Thread-safe core, delivers data with streams, accepts data with sinks.
- Core is not bound to any specific async-runtime. First implemented network transport uses websockets on tokio.
- Allows use of custom de/serializers, uses serde by default.
- Can be compiled to .so, has ruby binding (ffi), and wasm/js binding.

It's **not** meant for and won't do: message passing, remote function calls, synchronous "calls" (request-response), allow explicit target addressing, be a work-queue, allow "consuming" objects, work directly with any database, modify objects in transit.


## Usage example
```rust
let exchange = LocalExchange::builder().build();
let mut observe_contract = exchange.object((["some-tag"],"xxx")).observe();
let mut expose_contract = exchange.object((["some-tag"],"xxx")).expose();

tokio::spawn(async move {
	//ExposeContract emits ObjectStateSink when first observer appears
	let mut object_state_sink = expose_contract.next().await.unwrap();
	let object_state = ObjectState::new("my data").json_serialize();
	object_state_sink.send(object_state).await;
});

tokio::spawn(async move {
	//ObserveContract emits ObjectStateStream when exposer uploads first ObjectState
	let mut object_state_stream = observe_contract.next().await.unwrap();
	let object_state = object_state_stream.next().await.unwrap().json_deserialize::<String>();
	println!("{:?}", object_state.data);
});
```

For more examples check out the `examples` directory, and [documentation](https://docs.rs/hakuban/).

## Related projects

### [Ruby binding](https://gitlab.com/yunta/hakuban-ruby)

Hakuban ruby ffi binding.

### [Wasm/JS for browser](https://www.npmjs.com/package/hakuban)

Hakuban compiled to wasm, with JS interface to use in browser.

### Hakuban webapp router 
`(TODO: add url)`

Webapp router, with following properties:
* Every link is open-in-new-tab compatible, and copy-link compatible
* Short urls, optionally exposing selected state variables
* All urls (== application states) are shareable
* State can be bigger than what fits in a url (as long as it's built progressively)
* Works while offline/disconnected (no url shortening then)

### Schedy
`(TODO: add url)`

Task queue/scheduler. Aware of resource preparation time. Resources owned and resources required by task are graph-structured.

### [MechaTouch](https://mikoton.com/pages/mechatouch.html)

Commercial (aka. shameless plug) robotic ui-testing platform, with visual test-scenario programming, fully remote SUT control, zero-overhead performance measurements, etc. 

## Roadmap
Not ordered by priority:
- preloading/side loading
- avoid object flicker on short disconnections
- message filter for auth* and auditing
- immunity to broken/malicious diffs
- expose introspection/statistics objects
- more efficient and simpler network protocol
- hold un-serialized objects, and serialize only when/if needed

## License

Distributed under the MIT License. See `LICENSE` for more information.


## Contact

To get help, praise the author(s), laugh at problems of others, or just hang around observing progress - join hakuban's matrix channel [#hakuban:matrix.org](matrix:r/hakuban:matrix.org)

If you're looking for more intimate contact, talk to `yunta` - on matrix [@yunta:mikoton.com](matrix:u/yunta:mikoton.com), or email yunta@mikoton.com.


## Similar projects

The list does not contain change- or message- focused projects, nor projects with integrated database. Hopefully. It's surprisingly difficult to figure out what some of those actually do:
* [Redis](https://redis.io)
* [driftdb](https://driftdb.com/)
* [Fluvio](https://www.fluvio.io/)
* [deepstream](https://deepstream.io/)
* [zenoh](https://zenoh.io/) 
* [Ably](https://ably.com/)
* just diffing, if you don't need the network and lifetime control parts:
	* [serde-diff](https://github.com/amethyst/serde-diff)
	* [dipa](https://github.com/chinedufn/dipa)
	* [deltoid](https://github.com/jjpe/deltoid)

