Synchronization Engine & Domain
HTTP replication (Pull & Push), workspace connections, and the time-entry lifecycle.
Synchronization Engine & Domain
Mr. Tick uses a provider-agnostic synchronization engine based on HTTP Replication (Pull & Push of Deltas). Rather than opening persistent connections such as WebSockets or aggressively polling third-party APIs, it synchronizes data in a structured, efficient way that tolerates network failures.
π How HTTP Replication Works
Synchronization between Mr. Tick and a server or management tool (Redmine, Jira, YouTrack, etc.) has two distinct cycles: Pull and Push.
ββββββββββββββββββββββββββββββββ
β Local DB (Mr-tick) β
ββββββββ¬βββββββββββββββββ²βββββββ
β β
[1] Pull (Download) β [2] Push (Upload)
Tasks, Categories, β New Time Entries,
Metadata & Checkpoints β Updates and Deletes
β β
βΌ β
βββββββββββββββββββββββββ΄βββββββ
β Remote Server (API) β
ββββββββββββββββββββββββββββββββ1. Pull Phase (Downloading Data & Deltas)
Pull retrieves only remote data created or updated since the last synchronization.
Executor Services:
TaskPullService: Downloads tasks/issues assigned to the authenticated member.TimeEntriesPullService: Downloads time entries already stored on the server.MetadataPullService: Downloads essential metadata such as allowed activities, categories, and projects.
checkpoint and batch:
To avoid overloading external APIs or repeatedly downloading the entire history:
- Mr. Tick sends a
checkpoint, which can be an ISO 8601 timestamp or cursor. - The DataSource API returns changes after that
checkpoint, limited bybatchsize (for example, 50 items per page). - Once a batch is processed successfully, Mr. Tick stores the new
checkpointlocally.
// Exemplo conceitual do mΓ©todo pull na interface de consulta
public async pull(memberId: string, checkpoint?: string, batch: number = 50): Promise<TaskDTO[]> {
const url = checkpoint
? `/api/tasks?updated_after=${checkpoint}&limit=${batch}`
: `/api/tasks?limit=${batch}`
const response = await httpClient.get(url)
return response.data.map(mapToTaskDTO)
}2. Push Phase (Uploading Time Entries & Detecting Conflicts)
Push sends local time entries that were created, edited, or deleted to the remote provider through TimeEntriesPushService.
Batch Processing Flow:
Every batch item (SyncTimeEntryDTO) passes through a strict pipeline:
- Document Validation:
- A document must have valid
idandupdatedAtvalues.
- A document must have valid
- Deletion Handling (
_deleted: true):- When an entry is deleted locally, Mr. Tick calls
timeEntryRepository.delete(id)on the remote server and marks it as synchronized (syncedAt: new Date()).
- When an entry is deleted locally, Mr. Tick calls
- Conflict Detection (Optimistic Concurrency Control):
- When a record already exists remotely, Mr. Tick compares the server's
updatedAtwith the client'sassumedMasterState.updatedAt. - No Conflict: Compatible records have their times and comments updated remotely and confirmed with
syncedAt. - Conflict: If someone modified the remote record after the last local read, the item is marked
conflicted: truewith{ server: existing, local: entry }for safe resolution without data loss.
- When a record already exists remotely, Mr. Tick compares the server's
- Creating New Time Entries:
- When a record does not exist remotely, the
TimeEntryentity is validated and persisted throughtimeEntryRepository.create().
- When a record does not exist remotely, the
π’ Workspaces & DataSource Connections
In Mr. Tick, all data context belongs to a Workspace.
Workspace Responsibilities:
- A workspace provides tenant isolation (for example, "Company A", "Company B", "Freelance Consulting").
- Each workspace has its own tasks, time-entry history, and preference settings.
Connection Structure (DataSourceConnection):
A workspace can have multiple connections to external tools:
type DataSourceConnection = {
id: string // Identificador da conexΓ£o (ex: "conn-jira-prod")
dataSourceId: string // ID do plugin (ex: "jira-datasource")
status: 'connected' | 'disabled' | 'disconnected'
member?: {
// Dados do usuΓ‘rio autenticado nessa ferramenta
id: string
name: string
login: string
avatarUrl?: string
}
config?: Record<string, unknown> // ConfiguraΓ§Γ΅es especΓficas (ex: baseUrl, tenant)
}IDataSourceResolver receives the workspaceId and connectionInstanceId, instantiates the correct adapter at runtime, and injects secure credentials.
β±οΈ Domain Entities: Time Entries and Tasks
The @mr-tick/domain layer ensures consistency of time data:
TimeEntry Entity
Required validation rules:
- Time Calculation (
timeSpent): WhenstartDateandendDateare provided, duration in seconds is validated against the actual date interval. End dates cannot precede start dates. - Comments: An optional field limited to 255 characters, with whitespace sanitization.
- Activity & Task: Every time entry must reference a task and an activity (a work category such as "Development", "Meeting", or "Code Review").
Task Entity
- Contains a title (at least 3 characters), description,
workspaceId, and optional external-ID references (externalId,externalType). - Fallback Task (
createFallback): When a user starts a timer without selecting a task, Mr. Tick creates a fallback General Task so worked time is not lost.