- C++ 71.7%
- C 18.9%
- Meson 6.1%
- Python 3%
- Shell 0.3%
|
Jens Finkhaeuser
0befebc940
Some checks failed
/ build-meson (arm64, map[cc:clang cxx:clang++]) (push) Successful in 6m36s
/ build-meson (arm64, map[cc:gcc cxx:g++]) (push) Successful in 5m12s
/ build-conan (arm64) (push) Successful in 7m23s
/ checks (push) Has been cancelled
/ build-meson (x86_64, map[cc:clang cxx:clang++]) (push) Has been cancelled
/ build-meson (x86_64, map[cc:gcc cxx:g++], true, true) (push) Has been cancelled
/ build-conan (x86_64) (push) Has been cancelled
/ build-android (android-arm64-v8a.conan) (push) Has been cancelled
/ build-android (android-armeabi-v7a.conan) (push) Has been cancelled
/ build-android (android-x86.conan) (push) Has been cancelled
/ build-android (android-x86_64.conan) (push) Has been cancelled
|
||
|---|---|---|
| .forgejo/workflows | Disable appveyor builds for now | |
| .well-known | Add well-known funding url | |
| changelog.d | Add changelog | |
| docs | Bump version: 0.1.0 → 0.1.1 | |
| include | (void) and () have different meanings in C | |
| lib | Vessel handles need to also release iterator | |
| scripts | Delete appveyor file | |
| subprojects | The branch no longer exists/has been merged | |
| test | Drop names from unused parameters | |
| .bumpversion.cfg | Bump version: 0.1.0 → 0.1.1 | |
| .gitignore | Try this as a skeleton project for Tony | |
| .gitmodules | Try this as a skeleton project for Tony | |
| .oclint | Try this as a skeleton project for Tony | |
| .semgrepignore | Try this as a skeleton project for Tony | |
| AUTHORS | Try this as a skeleton project for Tony | |
| build-config.h.in | WIP | |
| CHANGES | Generate changelog | |
| CODE_OF_CONDUCT.md | Try this as a skeleton project for Tony | |
| codemeta.json | Try this as a skeleton project for Tony | |
| conandata.yml | Include missing header, and set dependency to vessel 0.1.1 | |
| conanfile.py | Adjust conanfile to 2.x | |
| CONTRIBUTING.md | Fix docs | |
| DCO.txt | Try this as a skeleton project for Tony | |
| LICENSE | Try this as a skeleton project for Tony | |
| meson.build | Bump version: 0.1.0 → 0.1.1 | |
| meson_options.txt | WIP | |
| Pipfile | Merge branch 'main' into documentation | |
| Pipfile.lock | Bump dependencies | |
| README.md | Update README | |
| towncrier.toml | Try this as a skeleton project for Tony | |
Wyrd
Build status Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.
An API and plugin interface for treating documents as a series of changes, and synchronizing them across nodes.
Wyrd provides access to documents as a tree structure of properties which can have different data types. In that sense, it is semantically similar to the document representation of e.g. a HTML document, or a nested JSON structure, etc.
Properties are conflict-free replicated data types (CRDTs). Since there exist a number of different CRDTs, when setting a property value, you can also specify a merge strategy, which is effectively a choice of CRDT implementation. When overwriting the value, the merge strategy generates an edit, which can be serialized, sent over a network, and applied on a different node.
The basic implementation uses a file for synchronization: edits are written to a file, and the property tree is reconstructed when the file is read.
However, wyrd also integrates with vessel, which is a container format specifically designed for synchronizing across network nodes. When integrating with vessel, wyrd is more or less equivalent to a Merkle CRDT.
Project Info
| ChangeLog | Contributing | Code of Conduct |
|---|
💡 Usage
Being a library, the first thing you need to do is instanciate a library handle. This handle contains "global" values, which allows you to run multiple instances in parallel (though that should not be necessary very often):
#include <wyrd/api.h>
/* ... */
struct wyrd_api * api = NULL;
wyrd_error_t err;
err = wyrd_create(&api);
/* use the API instance *
err = wyrd_destroy(&api);
Within the scope of creating and destroying the API instance, you can create as many handles as you need. A handle represents a resource, such as a file or vessel resource.
struct wyrd_handle * handle = NULL;
/* e.g. */
err = wyrd_open_file(api, &handle, "my-file", WYRD_O_RW| WYRD_O_CREATE);
/* use the handle */
err = wyrd_close(&handle);
With an open handle, you can then set and modify properties by name. Property
names are strings, but the special . (dot) character separates path segments.
Wyrd knows several container property types, such as maps and lists. In this
way, a path such as "foo.bar" accesses the property bar which is a child
of the foo property, which is in turn a map. Similarly, "foo.0" would
access the first element if foo was a list, etc.
In the following example we use the "naive override" merge strategy, which is the simplest form of CRDT - so simple it barely counts. With this strategy, the last change always wins, naively overriding any previous value. But for demonstrating the API, it is the simplest choice:
err = wyrd_set_property_uint16(handle, "foo", WYRD_MS_NAIVE_OVERRIDE, 42);
assert(WYRD_ERR_SUCCESS == wyrd_check_property_type(handle, "foo", WYRD_PT_UINT16));
assert(WYRD_ERR_SUCCESS == wyrd_check_merge_strategy(handle, "foo", WYRD_MS_NAIVE_OVERRIDE));
Finally, for the purpose of reacting to updates from remote nodes, you can register callbacks to be invoked when a property changes.
void my_callback(struct wyrd_handle * handle, char const * path, wyrd_property_type type,
void const * value, size_t value_size, void * baton)
{
// This callback can only deal with unchanged property *types*; a more realistic
// scenario should check the type and act accordingly.
assert(WYRD_PT_UINT16 == type);
assert(value_size == sizeof(uint16_t));
uint16_t val = *((uint16_t const *) value);
// ...
}
err = wyrd_add_property_callback(handle, "foo", my_callback, NULL);
Whichever you pass as the final parameter to wyrd_add_property_callback will
be provided to the callback as the baton parameter. Take care of memory
ownership/life cycles with this parameter, as the value cannot be copied.
📖 API
The API is growing as the needs of the Interpeer Project change. The full documentation provides How-Tos and an API reference.
🛠️ Installation
If you're using meson, just put this repo (at a version tag of your choice) into your subprojects as a submodule, e.g.
$ git submodule add https://codeberg.org/interpeer/wyrd subprojects/wyrd
$ cd subprojects/wyrd
$ git checkout v0.1.0 # or whatever
$ cd ..
$ git commit -m "Added wyrd at v0.1.0"
When that is done, you can just use wyrd in your own meson.build file.
# Try system wyrd first, fall back to subproject
wyrd_dep = dependency(
'wyrd',
fallback: ['wyrd']
)
# Assuming you're building a list of dependencies
deps += [wyrd_dep]
summary('wyrd', wyrd_dep.version(), section: 'Interpeer Dependencies')
⚖️ License
Wyrd is licensed under the GNU General Public License; a copy of the license is in the repository.
For other licensing options, please contact Interpeer gUG.
We're a non-profit, however, so if you like this library, please consider donating ❤️. That will make sure the code stays maintained.