External Sync Config
Overview
The External Sync system in DataCollect provides a unified interface for synchronizing data with external third-party systems. It implements the Strategy pattern to support multiple external system integrations through pluggable adapters.
The system aims to:
This configuration is typically used by sync server instances to synchronize data with external systems. The sync server reads this configuration to understand the data structure, authentication requirements, and sync endpoints needed to properly exchange data with external systems like OpenSPP, OpenFn, or other third-party platforms.
Sample Configuration
Here's a complete example of an external sync configuration with detailed field explanations:
{
"externalSync": {
"type": "openfn-adapter",
"url": "https://api.openfn.org/workflow/trigger/abc123",
"extraFields": [
{
"name": "apiKey",
"value": "sk_prod_1234567890abcdef"
},
{
"name": "workflowId",
"value": "wf_1234567890"
},
{
"name": "batchSize",
"value": "50"
},
{
"name": "timeout",
"value": "30000"
}
]
}
}
Field Explanations
type (Required)
- Purpose: Specifies which adapter to use for synchronization
- Values:
"mock-sync-server"- For testing and development"openfn-adapter"- For OpenFn workflow integration- Custom adapter types as defined in your system
- Example:
"openfn-adapter"
url (Required)
- Purpose: The endpoint URL of the external system for data synchronization
- Format: Full URL including protocol, domain, and path
- Examples:
"https://api.openfn.org/workflow/trigger/abc123""http://localhost:3000/mock-sync""https://your-external-system.com/api/sync"
extraFields (Required Array)
-
Purpose: Additional configuration parameters specific to the adapter type
-
Structure: Array of objects with
nameandvalueproperties -
Common Fields:
For OpenFn Adapter:
apiKey: Your OpenFn API key for authenticationworkflowId: The specific workflow ID to triggerbatchSize: Number of records to process in each batch (default: 100)timeout: Request timeout in milliseconds (default: 30000)
For Mock Sync Server:
batchSize: Number of events to process per batchretryAttempts: Number of retry attempts for failed requestsdelayBetweenBatches: Delay in milliseconds between batch processing
For Custom Adapters:
- Any adapter-specific configuration parameters
- Database connection strings
- Custom headers or authentication tokens
- Sync frequency settings
Configuration Examples by Adapter Type
Mock Sync Server Configuration
{
"type": "mock-sync-server",
"url": "http://localhost:3000/mock-sync",
"extraFields": [
{ "name": "batchSize", "value": "25" },
{ "name": "retryAttempts", "value": "3" }
]
}
OpenFn Adapter Configuration
{
"type": "openfn-adapter",
"auth": "api-key",
"url": "https://api.openfn.org/workflow/trigger/def456",
"extraFields": [
{ "name": "apiKey", "value": "sk_prod_abcdef123456" },
{ "name": "workflowId", "value": "wf_abcdef123456" },
{ "name": "batchSize", "value": "50" },
{ "name": "timeout", "value": "60000" }
]
}
Custom External System Configuration
{
"type": "custom-adapter",
"auth": "basic",
"url": "https://your-system.com/api/sync",
"extraFields": [
{ "name": "username", "value": "sync_user" },
{ "name": "password", "value": "secure_password" },
{ "name": "database", "value": "production_db" },
{ "name": "syncInterval", "value": "300000" }
]
}
Architecture
Design Pattern
The External Sync system uses the Strategy pattern to handle different external system integrations:
- Context:
ExternalSyncManageracts as the context that manages the synchronization strategy - Strategy: Each adapter (e.g.,
MockSyncServerAdapter,OpenFnSyncAdapter) implements theExternalSyncAdapterinterface - Registry: The
adaptersMappingobject serves as a registry of available strategies
Key Components
const adaptersMapping = {
"mock-sync-server": MockSyncServerAdapter,
"openfn-adapter": OpenFnSyncAdapter,
};
Configuration
ExternalSyncConfig Interface
The configuration is defined by the ExternalSyncConfig type:
type ExternalSyncConfig = {
type: string; // Adapter type identifier
auth?: string; // Authentication method
url: string; // External system URL
extraFields: { name: string; value: string }[]; // Additional configuration
};
Configuration in Admin UI
The Admin interface provides a user-friendly way to configure external sync settings.
Available Adapters
1. Mock Sync Server Adapter
Type: mock-sync-server
A testing adapter that simulates external system synchronization:
- Push: Sends events to a mock server endpoint
- Pull: Retrieves data from the mock server
- Batch Processing: Processes events in configurable batches (default: 100)
- Timestamp Tracking: Maintains sync timestamps for incremental sync
Configuration:
{
"type": "mock-sync-server",
"url": "http://localhost:3000/mock-sync",
"extraFields": []
}
2. OpenFn Adapter
Type: openfn-adapter
Integration with OpenFn workflow automation platform:
- Push: Sends entities to OpenFn workflows via API
- Authentication: Uses API key authentication
- Pull: Not yet implemented (planned for future)
Configuration:
{
"type": "openfn-adapter",
"url": "https://api.openfn.org/workflow/trigger",
"extraFields": [
{ "name": "apiKey", "value": "your-api-key" }
]
}
Usage Examples
Basic Initialization
import { ExternalSyncManager } from './components/ExternalSyncManager';
import { EventStore } from './interfaces/types';
import { EventApplierService } from './services/EventApplierService';
// Configuration
const config: ExternalSyncConfig = {
type: 'mock-sync-server',
url: 'http://localhost:3000/sync',
extraFields: []
};
// Initialize manager
const manager = new ExternalSyncManager(
eventStore,
eventApplierService,
config
);
// Initialize adapter
await manager.initialize();
// Check if adapter was loaded
if (manager.isInitialized()) {
await manager.synchronize();
}
With Authentication
const credentials: ExternalSyncCredentials = {
username: 'sync_user',
password: 'secure_password'
};
await manager.synchronize(credentials);
Error Handling
try {
await manager.initialize();
if (manager.isInitialized()) {
await manager.synchronize();
console.log('Sync completed successfully');
} else {
console.error('No adapter available for type:', config.type);
}
} catch (error) {
if (error.message === 'Adapter not initialized') {
console.error('Please call initialize() first');
} else {
console.error('External sync failed:', error.message);
}
}
API Reference
Constructor
constructor(
eventStore: EventStore,
eventApplierService: EventApplierService,
config: ExternalSyncConfig
)
Parameters:
eventStore: Store for managing events and audit logseventApplierService: Service for applying events to entitiesconfig: Configuration object specifying the external system type and settings
Methods
initialize(): Promise<void>
Initializes the external sync manager by instantiating the appropriate adapter.
Behavior:
- Looks up the adapter class based on configuration type
- Creates an instance with provided dependencies
- If adapter type not found, manager remains uninitialized
Throws: Error when adapter instantiation fails
synchronize(credentials?: ExternalSyncCredentials): Promise<void>
Performs synchronization with the external system using the configured adapter.
Parameters:
credentials: Optional authentication credentials for the external system
Behavior:
- Delegates sync operation to the loaded adapter
- Handles system-specific integration logic
- Typically involves pulling/pushing data and applying changes
Throws: Error when adapter is not initialized or sync operation fails
isInitialized(): boolean
Checks if the external sync manager has been properly initialized with an adapter.
Returns: true if an adapter is loaded and ready for synchronization
Integration with DataCollect System
Event Sourcing Integration
The External Sync system integrates with DataCollect's event sourcing architecture:
- Event Store: Tracks all form submissions and maintains sync timestamps
- Event Applier Service: Applies pulled events to local entities
- Sync Levels: Manages synchronization state (LOCAL, REMOTE, EXTERNAL)
Sync Process Flow
-
Push Phase:
- Retrieve events since last push timestamp
- Send events to external system in batches
- Update push timestamp after successful batch
-
Pull Phase:
- Retrieve data from external system since last pull
- Convert external data to FormSubmission events
- Apply events using EventApplierService
- Update pull timestamp
Timestamp Management
The system maintains separate timestamps for:
lastPushExternalSyncTimestamp: Last successful push to external systemlastPullExternalSyncTimestamp: Last successful pull from external system
This enables incremental synchronization and prevents data loss.
Extending the System
Adding New Adapters
To add support for a new external system:
- Create Adapter Class:
class CustomSyncAdapter implements ExternalSyncAdapter {
constructor(
private eventStore: EventStore,
private eventApplierService: EventApplierService,
private config: ExternalSyncConfig
) {}
async sync(credentials?: ExternalSyncCredentials): Promise<void> {
// Implement sync logic
}
}
- Register in Adapters Mapping:
const adaptersMapping = {
"mock-sync-server": MockSyncServerAdapter,
"openfn-adapter": OpenFnSyncAdapter,
"custom-adapter": CustomSyncAdapter, // Add new adapter
};
- Update Admin UI:
<v-select
v-model="form.externalSync.type"
:items="[
{ title: 'Mock Sync Server', value: 'mock-sync-server' },
{ title: 'OpenFn', value: 'openfn-adapter' },
{ title: 'Custom System', value: 'custom-adapter' }, // Add new option
]"
label="Type"
/>
Configuration Schema
Each adapter can define its own configuration schema by extending ExternalSyncConfig:
interface CustomSyncConfig extends ExternalSyncConfig {
database?: string;
timeout?: number;
retryAttempts?: number;
}
Best Practices
Error Handling
- Always check
isInitialized()before callingsynchronize() - Implement proper error handling for network failures
- Use try-catch blocks around sync operations
Performance
- Use batch processing for large datasets
- Implement incremental sync using timestamps
- Consider implementing retry logic for failed operations
Security
- Store sensitive credentials securely
- Use HTTPS for external system communication
- Implement proper authentication mechanisms
Monitoring
- Log sync operations for debugging
- Track sync success/failure rates
- Monitor sync performance metrics
Related Components
- ConfigCreateView.vue: Admin UI for configuring external sync
- MockSyncServerAdapter: Testing adapter for development
- OpenFnSyncAdapter: OpenFn platform integration
- EventStore: Event storage and timestamp management
- EventApplierService: Event application to entities
Troubleshooting
Common Issues
-
Adapter Not Found
- Ensure the adapter type is correctly registered in
adaptersMapping - Check that the adapter class is properly imported
- Ensure the adapter type is correctly registered in
-
Authentication Failures
- Verify credentials are correctly formatted
- Check that the external system accepts the authentication method
-
Sync Failures
- Check network connectivity to external system
- Verify the external system URL is correct
- Review error logs for specific failure reasons
-
Data Loss
- Ensure timestamps are properly maintained
- Check that incremental sync is working correctly
- Verify event ordering and processing
Debug Mode
Enable debug logging to troubleshoot sync issues:
// Enable detailed logging
console.log('Sync configuration:', config);
console.log('Adapter initialized:', manager.isInitialized());
console.log('Sync timestamps:', {
lastPush: await eventStore.getLastPushExternalSyncTimestamp(),
lastPull: await eventStore.getLastPullExternalSyncTimestamp()
});