Implement incremental sync and offline recovery

This commit is contained in:
diyaa
2026-06-15 22:31:23 +02:00
parent fa7727d572
commit 295c6c1d9b
25 changed files with 2293 additions and 494 deletions
+68 -89
View File
@@ -395,18 +395,7 @@
"/api/v1/sync/bootstrap": {
"get": {
"operationId": "SyncController_bootstrap_v1",
"parameters": [
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
}
],
"parameters": [],
"responses": {
"200": {
"description": "",
@@ -434,23 +423,24 @@
"operationId": "SyncController_changes_v1",
"parameters": [
{
"name": "deviceId",
"required": false,
"in": "query",
"description": "Optional client metadata. Authorization: Bearer <deviceAccessToken> is required and determines access.",
"schema": {
"format": "uuid",
"type": "string"
}
},
{
"name": "after",
"name": "cursor",
"required": false,
"in": "query",
"schema": {
"example": "0",
"type": "string"
}
},
{
"name": "limit",
"required": false,
"in": "query",
"schema": {
"minimum": 1,
"maximum": 500,
"example": 100,
"type": "number"
}
}
],
"responses": {
@@ -918,26 +908,37 @@
"tracks"
]
},
"LibraryTrackDto": {
"SyncBootstrapResponseDto": {
"type": "object",
"properties": {
"id": {
"nextCursor": {
"type": "string",
"format": "uuid"
"example": "7"
},
"title": {
"type": "string",
"example": "Placeholder Track"
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RemoteLibraryTrackDto"
}
},
"artist": {
"serverTime": {
"type": "string",
"example": "Velody"
"example": "2026-06-15T12:00:00.000Z"
}
}
},
"required": [
"nextCursor",
"tracks",
"serverTime"
]
},
"SyncEventDto": {
"type": "object",
"properties": {
"cursor": {
"type": "string",
"example": "3"
},
"entityType": {
"type": "string",
"example": "TRACK"
@@ -948,56 +949,33 @@
},
"action": {
"type": "string",
"example": "CREATED"
"example": "UPDATED"
},
"eventId": {
"track": {
"nullable": true,
"type": "object",
"allOf": [
{
"$ref": "#/components/schemas/RemoteLibraryTrackDto"
}
]
},
"deletedTrackId": {
"type": "object",
"format": "uuid",
"nullable": true
},
"createdAt": {
"type": "string",
"example": "0"
"example": "2026-06-15T12:00:00.000Z"
}
},
"required": [
"cursor",
"entityType",
"entityId",
"action",
"eventId"
]
},
"SyncBootstrapResponseDto": {
"type": "object",
"properties": {
"nextCursor": {
"type": "string",
"example": "0"
},
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LibraryTrackDto"
}
},
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SyncEventDto"
}
},
"deletedTrackIds": {
"type": "array",
"items": {
"type": "string"
}
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
}
},
"required": [
"nextCursor",
"tracks",
"events",
"deletedTrackIds",
"serverTime"
"createdAt"
]
},
"SyncChangesResponseDto": {
@@ -1005,13 +983,20 @@
"properties": {
"nextCursor": {
"type": "string",
"example": "0"
"example": "7"
},
"tracks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LibraryTrackDto"
}
"hasMore": {
"type": "boolean",
"example": false
},
"requiresBootstrap": {
"type": "boolean",
"example": false
},
"reason": {
"type": "object",
"nullable": true,
"example": "cursor_too_old"
},
"events": {
"type": "array",
@@ -1019,22 +1004,16 @@
"$ref": "#/components/schemas/SyncEventDto"
}
},
"deletedTrackIds": {
"type": "array",
"items": {
"type": "string"
}
},
"serverTime": {
"type": "string",
"example": "2026-05-24T20:00:00.000Z"
"example": "2026-06-15T12:00:00.000Z"
}
},
"required": [
"nextCursor",
"tracks",
"hasMore",
"requiresBootstrap",
"events",
"deletedTrackIds",
"serverTime"
]
}