This page describes common use cases and suggested solutions for application architecture based on dinemic framework. This is not exhaustive, but could help you when designing your first applications
Resources spread over multiple hosts
Dinemic is designed to work across network to help you with managing decentralized resources. To manage them properly and take all advantages from dinemic framework let’s try to stick with following rules. First of all you need to recall that:
- model definitions (DModel class) is known only in application. Database model schema is not sticked to nodes or database. It is application specific thing and it should be installed on all nodes within your application, by properly defining DModel class derives and its instances
- each object created with dinemic DModel (or derived class) is known after short time across all cluster, by all dinemic-based applications
- public key of each object is also known after short time, as soon as information about new object is shared
- private key is known only on host, where object was created for the first time
- recreating object from its ID will not cause owning this model
- by authorizing other object, you can act as object owner on host, which owns that model, but only on host which owns private keys of authorized object (so the host, where authorized object was created for the first time)
So, with above rules in your mind, you can think about designing data in Dinemic database, to properly manage resources with respect to all authorized/unauthorized operations:
- Create model that represents single resource abstract
- Create single object that represent each instance of resource
- Create additional model of tenant/user/administrator/actor that will be able to act as authorized object to change single resource
- Create objects of tenants/users/administrators/actors to represent acting subjects, to be able to modify state of resource
- Assign tenants/users/administrators/actors to resource object as read and update authorized objects
Above design might be very similar to existing ones, known from common databases. However you should keep in mind our initial rules and fact, that for some object’s fields it won’t be possible to update and read them as unauthorized object. Above design also should be aligned to your exact flow in application and user/resource creation.
Next, let’s think about application logics design:
- Add listener to catch all updates of objects representing resources
- Ignore unauthorized updates on all nodes except nodes owning modified object (by throwing DUpdateRejected exception)
- On node that owns resource, process unauthorized update. Check for old/new values of changed field and create the same modification, but as yourself, to the same object. New modification will be signed by resource’s private key
- Use nodes representing tenants/users/administrators/actors to authorize other tenants/… to modify resource if necessary
- Remember, that when node owning the resource is not available, it won’t be able to sign such update. This should not be divided, by authorizing such update by others!
Modifying object as another object
This schema could be used when you need to update object, and you are not an owner:
- Check if object is owned by you
- If so, you can make modification
- If not, re-create object from its ID. Check for update_authorized_objects list in this object and check if any object on your host object has right to update that object
- If so, re-create owned object by its ID. Then re-create desired object with caller pointing to owned object with owned key, which is authorized to update
- All updates of this object will be signed by authorized object, which was passed as the caller
This makes possible to allow one object (i.e. administrator) to make modifications on remote resource. Still you can check if updates are valid by listeners and reject them or overwrite by your new values.
Changing data and taking actions on such change?
When creating new data model and assinging some workflow, avoid following:
- Create/recreate object
- Update it’s state
- Take action on resources represented by this object
The update could be refused by some resons by existing listeners. Instead use following:
- Create listener with on_updated/on_owned_updated/on_authorized_updated action
- Assign listener to your model on each instance of application (usually we don’t distinguish where listener is created. Whole cluster should act in the same way)
- Create/recreate object
- Update it’s state
Then your reaction for your data update should be called exactly when data is updated. Due dinemic acts as multi node, decentralized ecosystem, meanwhile there could be an update that changes your data model and you no longer want to update this object. Also this allows to place listener properly in all listeners stack, for example to not interrupt unauthorized updates blockers.
By using proper flow, as in this example, you will create application and logics that works in each place of cluster, after installing it. Otherwise there is risk that creating such object will cause action only on single point of cluster.