Skip to content

Commit 76353dd

Browse files
committed
Measure latency.
1 parent c8f9973 commit 76353dd

File tree

7 files changed

+95
-12
lines changed

7 files changed

+95
-12
lines changed

demos/benchmarks/lib/app_config_template.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
// Edit lib/app_config.dart and enter your PowerSync project details.
33
class AppConfig {
44
static const String powersyncUrl = 'http://localhost:8080';
5+
static const String backendUrl = 'http://localhost:6060';
56
static const String token = '';
67
}

demos/benchmarks/lib/models/benchmark_item.dart

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,24 @@ class BenchmarkItem {
99
final String description;
1010

1111
final DateTime clientCreatedAt;
12+
final DateTime? clientReceivedAt;
1213

1314
final DateTime? serverCreatedAt;
1415

1516
BenchmarkItem(
1617
{required this.id,
1718
required this.description,
1819
required this.clientCreatedAt,
20+
this.clientReceivedAt,
1921
this.serverCreatedAt});
2022

2123
factory BenchmarkItem.fromRow(sqlite.Row row) {
2224
return BenchmarkItem(
2325
id: row['id'],
2426
description: row['description'] ?? '',
2527
clientCreatedAt: DateTime.parse(row['client_created_at']),
26-
serverCreatedAt: DateTime.tryParse(row['client_created_at'] ?? ''));
28+
clientReceivedAt: DateTime.tryParse(row['client_received_at'] ?? ''),
29+
serverCreatedAt: DateTime.tryParse(row['server_created_at'] ?? ''));
2730
}
2831

2932
static Stream<List<BenchmarkItem>> watchItems() {
@@ -35,26 +38,50 @@ class BenchmarkItem {
3538
});
3639
}
3740

41+
static updateItemBenchmarks() async {
42+
await for (var _ in db.onChange(['benchmark_items'],
43+
throttle: const Duration(milliseconds: 1))) {
44+
await db.execute(
45+
'''UPDATE benchmark_items SET client_received_at = datetime('now', 'subsecond') || 'Z' WHERE client_received_at IS NULL AND server_created_at IS NOT NULL''');
46+
}
47+
}
48+
3849
/// Create a new list
3950
static Future<BenchmarkItem> create(String description) async {
4051
final results = await db.execute('''
4152
INSERT INTO
4253
benchmark_items(id, description, client_created_at)
43-
VALUES(uuid(), ?, datetime())
54+
VALUES(uuid(), ?, datetime('now', 'subsecond') || 'Z')
4455
RETURNING *
4556
''', [description]);
4657
return BenchmarkItem.fromRow(results.first);
4758
}
4859

49-
/// Delete this item.
50-
Future<void> delete() async {
51-
await db.execute('DELETE FROM benchmark_items WHERE id = ?', [id]);
52-
}
53-
5460
/// Find list item.
5561
static Future<BenchmarkItem> find(id) async {
5662
final results =
5763
await db.get('SELECT * FROM benchmark_items WHERE id = ?', [id]);
5864
return BenchmarkItem.fromRow(results);
5965
}
66+
67+
/// Delete this item.
68+
Future<void> delete() async {
69+
await db.execute('DELETE FROM benchmark_items WHERE id = ?', [id]);
70+
}
71+
72+
Duration? get latency {
73+
if (clientReceivedAt == null) {
74+
return null;
75+
} else {
76+
return clientReceivedAt!.difference(clientCreatedAt);
77+
}
78+
}
79+
80+
Duration? get uploadLatency {
81+
if (serverCreatedAt == null) {
82+
return null;
83+
} else {
84+
return serverCreatedAt!.difference(clientCreatedAt);
85+
}
86+
}
6087
}

demos/benchmarks/lib/models/schema.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Schema schema = const Schema(([
44
Table('benchmark_items', [
55
Column.text('description'),
66
Column.text('client_created_at'),
7+
Column.text('client_received_at'),
78
Column.text('server_created_at'),
89
]),
910
]));

demos/benchmarks/lib/powersync.dart

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
// This file performs setup of the PowerSync database
2+
import 'dart:convert';
3+
import 'dart:io';
4+
5+
import 'package:http/http.dart' as http;
6+
27
import 'package:flutter/foundation.dart';
38
import 'package:logging/logging.dart';
49
import 'package:path/path.dart';
510
import 'package:path_provider/path_provider.dart';
611
import 'package:powersync/powersync.dart';
12+
import 'package:powersync_benchmarks/models/benchmark_item.dart';
713

814
import './app_config.dart';
915
import './models/schema.dart';
@@ -12,7 +18,9 @@ final log = Logger('powersync-supabase');
1218

1319
/// Use Supabase for authentication and data upload.
1420
class BackendConnector extends PowerSyncBackendConnector {
15-
BackendConnector();
21+
http.Client client;
22+
23+
BackendConnector() : client = http.Client();
1624

1725
@override
1826
Future<PowerSyncCredentials?> fetchCredentials() async {
@@ -31,7 +39,36 @@ class BackendConnector extends PowerSyncBackendConnector {
3139
return;
3240
}
3341

34-
// TODO: Implement
42+
var uri = Uri.parse('${AppConfig.backendUrl}/api/data');
43+
44+
var body = jsonEncode({
45+
'batch': transaction.crud.map((op) {
46+
if (op.op == UpdateType.put) {
47+
return {
48+
'op': 'PUT',
49+
'table': op.table,
50+
'id': op.id,
51+
'data': op.opData
52+
};
53+
} else if (op.op == UpdateType.patch) {
54+
return {
55+
'op': 'PATCH',
56+
'table': op.table,
57+
'id': op.id,
58+
'data': op.opData
59+
};
60+
} else if (op.op == UpdateType.delete) {
61+
return {'op': 'DELETE', 'table': op.table, 'id': op.id};
62+
}
63+
}).toList()
64+
});
65+
var response = await client.post(uri,
66+
headers: {'Content-Type': 'application/json'}, body: body);
67+
if (response.statusCode < 200 || response.statusCode >= 300) {
68+
throw http.ClientException(
69+
'Data upload failed with ${response.statusCode} ${response.body}');
70+
}
71+
3572
await transaction.complete();
3673
}
3774
}
@@ -55,7 +92,11 @@ Future<void> openDatabase() async {
5592
schema: schema, path: await getDatabasePath(), logger: attachedLogger);
5693
await db.initialize();
5794

95+
BenchmarkItem.updateItemBenchmarks();
96+
5897
var currentConnector = BackendConnector();
5998

60-
db.connect(connector: currentConnector);
99+
db.connect(
100+
connector: currentConnector,
101+
crudThrottleTime: const Duration(milliseconds: 1));
61102
}

demos/benchmarks/lib/widgets/benchmark_item_widget.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,24 @@ class ListItemWidget extends StatelessWidget {
1515

1616
@override
1717
Widget build(BuildContext context) {
18+
String latency =
19+
item.latency != null ? '${item.latency!.inMilliseconds}ms' : '';
20+
21+
String uploadLatency = item.uploadLatency != null
22+
? '${item.uploadLatency!.inMilliseconds}ms'
23+
: '';
24+
25+
String subtitle =
26+
'$latency / $uploadLatency / ${item.serverCreatedAt?.toIso8601String() ?? ''}';
1827
return Card(
1928
child: Column(
2029
mainAxisSize: MainAxisSize.min,
2130
children: <Widget>[
2231
ListTile(
23-
leading: const Icon(Icons.list), title: Text(item.description)),
32+
leading: const Icon(Icons.list),
33+
title: Text(item.description),
34+
subtitle: Text(subtitle),
35+
),
2436
Row(
2537
mainAxisAlignment: MainAxisAlignment.end,
2638
children: <Widget>[

demos/benchmarks/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ packages:
124124
source: sdk
125125
version: "0.0.0"
126126
http:
127-
dependency: transitive
127+
dependency: "direct main"
128128
description:
129129
name: http
130130
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010

demos/benchmarks/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies:
1616
logging: ^1.2.0
1717
universal_io: ^2.2.2
1818
sqlite_async: ^0.9.0
19+
http: ^1.2.2
1920

2021
dev_dependencies:
2122
flutter_test:

0 commit comments

Comments
 (0)