Replication
Restrictions
- only Entities inheriting from ConfinityEntity can be replicated
- only classes with public constructors without arguments can be replicated
Configuration
appsettings Key: ConfinityReplication
| Configuration Key | Description | Default |
|---|---|---|
| DisableReplications | Stops transmitting replication schedules. | false |
| BypassProxy | Ignores the system configured proxy. | false |
| SkipNegotiation | Skips the negotiation of the available transports (websockets, server sent events, long polling) and goes straight for websockets. | false |
| MaxConcurrentOutgoingTransactions | Number of transactions that are transmitted concurrently to public instances. Reduce to save memory. [Range: 1-100] | 10 |
| ReplicationHubSecret | required for public instances: Secret for replication authentication. | |
| Stages | required for author instance: see detail | |
| FinishedReplicationScheduleMaxAge | Days before finished replication schedules are cleaned up. |
The file appsettings.ConfinityReplication.json can optionally be created and used for the replication configuration.
Stage Configuration
appsettings Key: <custom> | RFC 1123 <custom>:
- contain no more than 253 characters
- contain only lowercase alphanumeric characters, '-' or '.'
- start with an alphanumeric character
- end with an alphanumeric character
The stage configuration consist of a stage key and an object containing the stage configuration.
| Configuration Key | Description | Default |
|---|---|---|
| Key | required: Internal key of the stage for referencing. This must not change. (same as <custom>) | |
| Order | required: The stages must be uniquely ordered from the author instance (0, implicit set) to to the latest public stage (highest). The publishing will happen in this order. | |
| Label | required: The displayed label shown to the author to identify the stage. | |
| Instances | required: see detail |
Example for author stage and web stage with two nodes:
// author
{
"ConfinityReplication": {
"web": {
"Key": "web",
"Order": 1,
"Label": "Public WWW",
"Instances": {
"public1": {
"Key": "public1",
"ServerUrl": "http://web1",
"Secret": "IAmSuperSecret"
},
"public2": {
"Key": "public2",
"ServerUrl": "http://web2",
"Secret": "IAmHidden"
}
}
}
}
}
// public1
"ConfinityReplication": {
"ReplicationHubSecret": "IAmSuperSecret"
}
// public2
"ConfinityReplication": {
"ReplicationHubSecret": "IAmHidden"
}
Instance Configuration
| Configuration Key | Description | Default |
|---|---|---|
| Key | required: The unique key to identify this instance. | |
| ServerUrl | required: The url to this instance. | |
| Secret | required: The password used to verify the login from the author instance. |
Change Replication Configuration
Add a new stage
Feel free to add new stages at any point of time. No downtime is required (with rolling update) and no data is lost. (only Stages with higher indexes can be added)
To add a stage:
- Configure new stage
- Start new stage
- Restart author stage
- Manually publish all entities
Add an instance to an existing stage / fix instance divergence (same stage)
This targets installations where you have multiple databases per stage. If you want to add a new instance with the same database just the configuration has to be updated.
Instances can be added to a stage at any point of time. No downtime is required (with rolling update) and no data is lost.
Warning
No data can be published during this change.
To add an instance:
- Configure new stage on all existing instances.
- On the author stage. Set the replication URL of all the instances where you add a new instance to something which does not exist. This disables all replication to that stage.
- Restart the author stage.
- Backup the database where you add a new instance.
- Restore the backup to your new instance's database.
- Start the new instance.
- Fix the replication URLs on your author stage.
- Restart the author stage.
- 🥳
Developers
For developers, the IReplicationService provides functionality to interact with the replication. Developers typically use it when implementing scheduled tasks or imports. A couple of things should be considered working with the replication.
Publishing direction
Defines how entities can be transferred between stages.
- Copy from author instance: Default behavior. Enables entities to be copied from the author- to public stages.
- Move to author instance: For entities that were created exclusively on public stages and are to be moved to the author stage. The replication is triggered automatically after the entity was created. When the replication finished, the entity gets deleted on the source stage.
- Use cases: form submissions, event registrations etc.
- Copy bidirectional: For entities that are edited on either author or public instances and need to remain synchronized. On public stages, the replication is triggered automatically after the entity was created or changed.
- Use cases: user profile...
To define the publishing direction, use the IReplicationConfiguration in you UseModule implementation:
public void UseModule(IApplicationBuilder app)
{
var replicationConfiguration = app.ApplicationServices.GetRequiredService<IReplicationConfiguration>();
replicationConfiguration.SetPublishDirectionRule<UserProfile>(PublishDirection.CopyBidirectional);
}
Entity versions
While Confinity supports historization of entities, the replication will always use the newest version at the time of execution.
Schedule only
If you don't want to wait for the transmission of your entities to all public stages, use a schedule date in the near future when calling IReplicationService.ReplicateAsync. The call will return immediately when all replication schedules were created and performs the transmission in the background.
Duplicate transactions
To reduce system load, no new replication transaction is created if a duplicate already exist.
The exact conditions under which a replication transaction is considered a duplicate:
- for the same instance
- containing the same entities
- same replication type (ChangeSort/AddUpdate/Delete)
- status is either Error or Scheduled
- ScheduledAt is before the new ScheduledAt time
Parallel replications
You must not call IReplicationService.ReplicateAsync again for the same entity, before previous replications terminated.
Cancel replications
Consider using IReplicationService.CancelAsync to cancel the replication for a bunch of entity ids. Be aware that thereby every transaction is cancelled that contains one of the given entities.
Entity deletion
There are two different ways to handle deletion.
Implicitly delete entities with the DbContext
When you remove entities with the IConfinityDbContext, replication schedules will be created automatically that delete the entity on all stages.
Advantage:
- Nothing to consider/remember while developing
Disadvantage
- If the replication fails, entities still exist on public stages but can't be seen on the author stage anymore, because there they were already deleted. To fix this, deploy a script that deletes those entities on public instances.
Explicitly delete entities with IReplicationService.DeleteAsync
Tips
This is the recommended way.
Use IReplicationService.DeleteAsync to explicitly delete entities on other stages. The parameter StageOption determines, if the entities should be deleted on all stages or on all but the author stage.
Advantage:
- Deletes the entities in the following order: public -> preview -> author and thereby ensures that the author stage always has the correct status
- If the replication fails on public, the entity still exists on author-stage and authors can still delete them manually
Disadvantage
- More code & developers must not forget to call it
- Can block the execution if replication is slow/offline and no
CancellationTokenis provided