docs(analytics,jobs): Work Order 3 batch 4 — device usage, popular books, job create/status
DeviceUsageResponse / PopularBooksResponse / services.JobResult pinned by type; jobs create uses an inline anonymous request struct (RawMessage pin). Two UNVERIFIED markers recorded (analytics date-range params, facet value element shape).
This commit is contained in:
1 parent
4a6fb033cb
commit
7471ca99e8
5 files changed
+169
No files matched your search
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
method: GET
|
||||||
|
path: /api/analytics/device-usage
|
||||||
|
auth: jwt
|
||||||
|
area: analytics
|
||||||
|
---
|
||||||
|
<!-- source: internal/handlers/analytics.go DeviceUsageResponse / GetDeviceUsage -->
|
||||||
|
|
||||||
|
# Get Device Usage
|
||||||
|
|
||||||
|
Per-device sync activity for the signed-in user.
|
||||||
|
|
||||||
|
## Example response
|
||||||
|
|
||||||
|
```json example-response
|
||||||
|
{
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"device_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"device_name": "Kobo Clara",
|
||||||
|
"device_type": "kobo",
|
||||||
|
"sync_count": 42,
|
||||||
|
"last_sync": "2026-10-24T13:57:01Z",
|
||||||
|
"total_time_seconds": 3600,
|
||||||
|
"total_time_minutes": 60
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query parameters
|
||||||
|
|
||||||
|
UNVERIFIED: accepts the standard analytics date-range params; confirm exact
|
||||||
|
names before relying on them.
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Body | When |
|
||||||
|
| ------ | ---- | ---- |
|
||||||
|
| 500 | `{"error": "..."}` | unexpected server error |
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
method: GET
|
||||||
|
path: /api/analytics/popular-books
|
||||||
|
auth: jwt
|
||||||
|
area: analytics
|
||||||
|
---
|
||||||
|
<!-- source: internal/handlers/analytics.go PopularBooksResponse / GetPopularBooks -->
|
||||||
|
|
||||||
|
# Get Popular Books
|
||||||
|
|
||||||
|
Most-read books for the signed-in user.
|
||||||
|
|
||||||
|
## Example response
|
||||||
|
|
||||||
|
```json example-response
|
||||||
|
{
|
||||||
|
"books": [
|
||||||
|
{
|
||||||
|
"media_item_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"title": "1984",
|
||||||
|
"author": "George Orwell",
|
||||||
|
"read_count": 3,
|
||||||
|
"avg_completion": 0.95,
|
||||||
|
"last_read": "2026-10-24T13:57:01Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query parameters
|
||||||
|
|
||||||
|
UNVERIFIED: accepts the standard analytics date-range params; confirm exact
|
||||||
|
names before relying on them.
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Body | When |
|
||||||
|
| ------ | ---- | ---- |
|
||||||
|
| 500 | `{"error": "..."}` | unexpected server error |
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
method: POST
|
||||||
|
path: /api/jobs
|
||||||
|
auth: jwt
|
||||||
|
area: jobs
|
||||||
|
---
|
||||||
|
<!-- source: internal/handlers/jobs.go CreateJob -->
|
||||||
|
|
||||||
|
# Create Job
|
||||||
|
|
||||||
|
Enqueues a background job (scan, import, convert — the set accepted by the
|
||||||
|
worker). Success is **202 Accepted** with the job id; poll its status via
|
||||||
|
`GET /api/jobs/:jobId`.
|
||||||
|
|
||||||
|
## Example request
|
||||||
|
|
||||||
|
```json example-request
|
||||||
|
{
|
||||||
|
"type": "import",
|
||||||
|
"params": { "library_id": "990e8400-e29b-41d4-a716-446655440000" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example response
|
||||||
|
|
||||||
|
```json example-response
|
||||||
|
{
|
||||||
|
"message": "Job created",
|
||||||
|
"job_id": "ee0e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"type": "import",
|
||||||
|
"status": "pending"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Body | When |
|
||||||
|
| ------ | ---- | ---- |
|
||||||
|
| 400 | `{"error": "Invalid job type"}` / others | unknown type or params |
|
||||||
|
| 500 | `{"error": "..."}` | enqueue failure |
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
method: GET
|
||||||
|
path: /api/jobs/:jobId
|
||||||
|
auth: jwt
|
||||||
|
area: jobs
|
||||||
|
---
|
||||||
|
<!-- source: internal/handlers/jobs.go:76 GetJobStatus; services/worker.go JobResult -->
|
||||||
|
|
||||||
|
# Get Job Status
|
||||||
|
|
||||||
|
Returns the in-memory status/result of a background job.
|
||||||
|
|
||||||
|
## Example response
|
||||||
|
|
||||||
|
```json example-response
|
||||||
|
{
|
||||||
|
"job_id": "ee0e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"status": "completed",
|
||||||
|
"error": "",
|
||||||
|
"result": null,
|
||||||
|
"progress": 100,
|
||||||
|
"files_scanned": 120,
|
||||||
|
"new_items": 3,
|
||||||
|
"errors": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`library_id` and `job_type` appear only on scan jobs (`omitempty`).
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Body | When |
|
||||||
|
| ------ | ---- | ---- |
|
||||||
|
| 404 | `{"error": "Job not found"}` | unknown id, or the in-memory result was evicted by a restart |
|
||||||
@@ -238,4 +238,20 @@ var Schemas = map[string]Schema{
|
|||||||
"GET /api/media-items/filter-count": {
|
"GET /api/media-items/filter-count": {
|
||||||
Response: json.RawMessage(`{"count": 0}`),
|
Response: json.RawMessage(`{"count": 0}`),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// --- analytics + jobs (batch 4) ---
|
||||||
|
"GET /api/analytics/device-usage": {
|
||||||
|
Response: handlers.DeviceUsageResponse{},
|
||||||
|
},
|
||||||
|
"GET /api/analytics/popular-books": {
|
||||||
|
Response: handlers.PopularBooksResponse{},
|
||||||
|
},
|
||||||
|
"POST /api/jobs": {
|
||||||
|
// Inline anonymous request struct {type, params} — pinned by sample.
|
||||||
|
Request: json.RawMessage(`{"type": "", "params": {}}`),
|
||||||
|
Response: json.RawMessage(`{"message": "", "job_id": "", "type": "", "status": ""}`),
|
||||||
|
},
|
||||||
|
"GET /api/jobs/:jobId": {
|
||||||
|
Response: services.JobResult{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user