Skip to content

Commit 8ebbe53

Browse files
committed
Merge branch 'main' into chore/formatting and run dotnet format
2 parents 81e98f2 + 2b75e9a commit 8ebbe53

File tree

21 files changed

+563
-1668
lines changed

21 files changed

+563
-1668
lines changed

PowerSync/PowerSync.Common/CHANGELOG.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,31 @@
11
# PowerSync.Common Changelog
22

3+
## 0.0.6-alpha.1
4+
- Updated to the latest version (0.4.10) of the core extension.
5+
- Dropping support for the legacy C# sync implementation.
6+
- Add `trackPreviousValues` option on `TableOptions` which sets `CrudEntry.PreviousValues` to previous values on updates.
7+
- Add `trackMetadata` option on `TableOptions` which adds a `_metadata` column that can be used for updates. The configured metadata is available through `CrudEntry.Metadata`.
8+
- Add `ignoreEmptyUpdates` option on `TableOptions` which skips creating CRUD entries for updates that don't change any values.
9+
- Reporting progress information about downloaded rows. Sync progress is available through `SyncStatus.DownloadProgress()`.
10+
- Support bucket priorities.
11+
- Report `PriorityStatusEntries` on `SyncStatus`.
12+
- Added ability to specify `AppMetadata` for sync/stream requests.
13+
14+
Note: This requires a PowerSync service version `>=1.17.0` in order for logs to display metadata.
15+
16+
```csharp
17+
db.Connect(connector, new PowerSync.Common.Client.Sync.Stream.PowerSyncConnectionOptions
18+
{
19+
// This will be included in PowerSync service logs
20+
AppMetadata = new Dictionary<string, string>
21+
{
22+
{ "app_version", myAppVersion },
23+
}
24+
});
25+
```
26+
327
## 0.0.5-alpha.1
4-
- Using the latest (0.4.9) version of the core extension, it introduces support for the Rust Sync implementation and also makes it the default - users can still opt out and use the legacy C# sync implementation as option when calling `connect()`.
28+
- Using the latest version (0.4.9) of the core extension, it introduces support for the Rust Sync implementation and also makes it the default - users can still opt out and use the legacy C# sync implementation as option when calling `connect()`.
529

630
## 0.0.4-alpha.1
731
- Fixed MAUI issues related to extension loading when installing package outside of the monorepo.
@@ -25,4 +49,4 @@
2549
* linux-x64
2650
* osx-arm64
2751
* osx-x64
28-
* wind-x64
52+
* wind-x64

PowerSync/PowerSync.Common/Client/PowerSyncDatabase.cs

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ public interface IPowerSyncDatabase : IEventStream<PowerSyncDBEvent>
8080

8181
public class PowerSyncDatabase : EventStream<PowerSyncDBEvent>, IPowerSyncDatabase
8282
{
83-
private static readonly int FULL_SYNC_PRIORITY = 2147483647;
84-
8583
public IDBAdapter Database;
8684
private Schema schema;
8785

@@ -156,21 +154,48 @@ public async Task WaitForReady()
156154
await isReadyTask;
157155
}
158156

159-
public async Task WaitForFirstSync(CancellationToken? cancellationToken = null)
157+
public class PrioritySyncRequest
158+
{
159+
public CancellationToken? Token { get; set; }
160+
public int? Priority { get; set; }
161+
}
162+
163+
/// <summary>
164+
/// Wait for the first sync operation to complete.
165+
/// </summary>
166+
/// <param name="request">
167+
/// An object providing a cancellation token and a priority target.
168+
/// When a priority target is set, the task may complete when all buckets with the given (or higher)
169+
/// priorities have been synchronized. This can be earlier than a complete sync.
170+
/// </param>
171+
/// <returns>A task which will complete once the first full sync has completed.</returns>
172+
public async Task WaitForFirstSync(PrioritySyncRequest? request = null)
160173
{
161-
if (CurrentStatus.HasSynced == true)
174+
var priority = request?.Priority;
175+
var cancellationToken = request?.Token;
176+
177+
bool StatusMatches(SyncStatus status)
178+
{
179+
if (priority == null)
180+
{
181+
return status.HasSynced == true;
182+
}
183+
return status.StatusForPriority(priority.Value).HasSynced == true;
184+
}
185+
186+
if (StatusMatches(CurrentStatus))
162187
{
163188
return;
164189
}
165190

166191
var tcs = new TaskCompletionSource<bool>();
167192
var cts = new CancellationTokenSource();
168193

169-
var _ = Task.Run(() =>
194+
_ = Task.Run(() =>
170195
{
171196
foreach (var update in Listen(cts.Token))
172197
{
173-
if (update.StatusChanged?.HasSynced == true)
198+
if (update.StatusChanged != null && StatusMatches(update.StatusChanged!))
174199
{
175200
cts.Cancel();
176201
tcs.SetResult(true);
@@ -192,7 +217,7 @@ protected async Task Initialize()
192217
await BucketStorageAdapter.Init();
193218
await LoadVersion();
194219
await UpdateSchema(schema);
195-
await UpdateHasSynced();
220+
await ResolveOfflineSyncStatus();
196221
await Database.Execute("PRAGMA RECURSIVE_TRIGGERS=TRUE");
197222
Ready = true;
198223
Emit(new PowerSyncDBEvent { Initialized = true });
@@ -216,48 +241,29 @@ private async Task LoadVersion()
216241
catch (Exception e)
217242
{
218243
throw new Exception(
219-
$"Unsupported PowerSync extension version. Need >=0.2.0 <1.0.0, got: {sdkVersion}. Details: {e.Message}"
244+
$"Unsupported PowerSync extension version. Need >=0.4.5 <1.0.0, got: {sdkVersion}. Details: {e.Message}"
220245
);
221246
}
222247

223-
// Validate version is >= 0.2.0 and < 1.0.0
224-
if (versionInts[0] != 0 || versionInts[1] < 2 || versionInts[2] < 0)
248+
// Validate version is >= 0.4.5 and < 1.0.0
249+
if (versionInts[0] != 0 || versionInts[1] < 4 || (versionInts[1] == 4 && versionInts[2] < 5))
225250
{
226-
throw new Exception($"Unsupported PowerSync extension version. Need >=0.2.0 <1.0.0, got: {sdkVersion}");
251+
throw new Exception($"Unsupported PowerSync extension version. Need >=0.4.5 <1.0.0, got: {sdkVersion}");
227252
}
228253
}
229254

230-
private record LastSyncedResult(int? priority, string? last_synced_at);
231-
232-
protected async Task UpdateHasSynced()
255+
private record OfflineSyncStatusResult(string r);
256+
protected async Task ResolveOfflineSyncStatus()
233257
{
234-
var results = await Database.GetAll<LastSyncedResult>(
235-
"SELECT priority, last_synced_at FROM ps_sync_state ORDER BY priority DESC"
236-
);
258+
var result = await Database.Get<OfflineSyncStatusResult>("SELECT powersync_offline_sync_status() as r");
259+
var parsed = JsonConvert.DeserializeObject<CoreSyncStatus>(result.r);
237260

238-
DateTime? lastCompleteSync = null;
261+
var parsedSyncStatus = CoreInstructionHelpers.CoreStatusToSyncStatus(parsed!);
262+
var updatedStatus = CurrentStatus.CreateUpdatedStatus(parsedSyncStatus);
239263

240-
// TODO: Will be altered/extended when reporting individual sync priority statuses is supported
241-
foreach (var result in results)
264+
if (!updatedStatus.IsEqual(CurrentStatus))
242265
{
243-
var parsedDate = DateTime.Parse(result.last_synced_at + "Z");
244-
245-
if (result.priority == FULL_SYNC_PRIORITY)
246-
{
247-
// This lowest-possible priority represents a complete sync.
248-
lastCompleteSync = parsedDate;
249-
}
250-
}
251-
252-
var hasSynced = lastCompleteSync != null;
253-
if (hasSynced != CurrentStatus.HasSynced)
254-
{
255-
CurrentStatus = new SyncStatus(new SyncStatusOptions(CurrentStatus.Options)
256-
{
257-
HasSynced = hasSynced,
258-
LastSyncedAt = lastCompleteSync,
259-
});
260-
266+
CurrentStatus = updatedStatus;
261267
Emit(new PowerSyncDBEvent { StatusChanged = CurrentStatus });
262268
}
263269
}
@@ -482,7 +488,7 @@ await Database.WriteTransaction(async tx =>
482488
return null;
483489
}
484490

485-
long? txId = first.TransactionId ?? null;
491+
long? txId = first.TransactionId;
486492
List<CrudEntry> all;
487493

488494
if (txId == null)

PowerSync/PowerSync.Common/Client/Sync/Bucket/BucketStorageAdapter.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,6 @@ public class BucketStorageEvent
9696
public interface IBucketStorageAdapter : IEventStream<BucketStorageEvent>
9797
{
9898
Task Init();
99-
Task SaveSyncData(SyncDataBatch batch);
100-
Task RemoveBuckets(string[] buckets);
101-
Task SetTargetCheckpoint(Checkpoint checkpoint);
102-
103-
void StartSession();
104-
105-
Task<BucketState[]> GetBucketStates();
106-
107-
Task<SyncLocalDatabaseResult> SyncLocalDatabase(Checkpoint checkpoint);
10899

109100
Task<CrudEntry?> NextCrudItem();
110101
Task<bool> HasCrud();
@@ -113,12 +104,6 @@ public interface IBucketStorageAdapter : IEventStream<BucketStorageEvent>
113104
Task<bool> HasCompletedSync();
114105
Task<bool> UpdateLocalTarget(Func<Task<string>> callback);
115106

116-
/// <summary>
117-
/// Exposed for tests only.
118-
/// </summary>
119-
Task AutoCompact();
120-
Task ForceCompact();
121-
122107
string GetMaxOpId();
123108

124109
/// <summary>

0 commit comments

Comments
 (0)