Compare commits

...

2 commits

Author SHA1 Message Date
58e046c1f0 Updated Program
Now utilizing syncers in an Array for each checking of IsDirty() or not,
and running code based upon the state of the syncers.  May clean this up
more.
Added polling of the database to see if there's anything new to sync
locally.
2025-07-30 12:20:50 -05:00
5887bc0961 Updated Syncer
Added interface for Syncer class.
Changed IsDirty from Property to Function
Moved order for reading in initial database.  First will fetch from the
REST Api, then it will read in the database stored locally.
Changed logic behind reading and fetching database.  Fetching the
database from the REST Api will mark internally that it is dirty, and
force syncing.
If an entry exists in our cache, and is equal, then we continue through,
otherwise we remove the old entry, and use the new entry.
2025-07-30 12:19:53 -05:00
2 changed files with 78 additions and 27 deletions

View file

@ -1,7 +1,9 @@
using Avalonia;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FreeTubeSyncer.Library;
@ -50,23 +52,49 @@ class Program
Syncer<Profile>? profileSyncer = null, Syncer<SearchHistory>? searchHistorySyncer = null,
Syncer<Setting>? settingsSyncer = null)
{
var syncers = new List<ISyncer>()
{
historySyncer,
playlistSyncer,
profileSyncer,
searchHistorySyncer,
settingsSyncer
};
var lastTime = DateTime.Now;
while (true)
{
Thread.Sleep(100);
if (Process.GetProcessesByName("FreeTube").Length > 0) continue;
Console.WriteLine("FreeTube has closed, we're going to try and update.");
Thread.Sleep(1500);
if (historySyncer is { IsDirty: true })
historySyncer.Sync();
if (playlistSyncer is { IsDirty: true })
playlistSyncer.Sync();
if (profileSyncer is { IsDirty: true})
profileSyncer.Sync();
if (searchHistorySyncer is { IsDirty: true})
searchHistorySyncer.Sync();
if (settingsSyncer is { IsDirty: true})
settingsSyncer.Sync();
if (syncers.Any(x => x != null && x.IsDirty() ))
{
Thread.Sleep(100);
if (lastTime - DateTime.Now > TimeSpan.FromSeconds(30))
{
foreach (var syncer in syncers)
syncer.FetchDatabase().Wait();
lastTime = DateTime.Now;
}
if (Process.GetProcessesByName("FreeTube").Length > 0) continue;
Console.WriteLine("FreeTube has closed and we have updates, we're going to try and update.");
Thread.Sleep(1500);
if (historySyncer != null && historySyncer.IsDirty())
historySyncer.Sync();
if (playlistSyncer != null && playlistSyncer.IsDirty())
playlistSyncer.Sync();
if (profileSyncer != null && profileSyncer.IsDirty())
profileSyncer.Sync();
if (searchHistorySyncer != null && searchHistorySyncer.IsDirty())
searchHistorySyncer.Sync();
if (settingsSyncer != null && settingsSyncer.IsDirty())
settingsSyncer.Sync();
}
else
{
Thread.Sleep(100);
if (lastTime - DateTime.Now <= TimeSpan.FromSeconds(30)) continue;
foreach (var syncer in syncers)
syncer.FetchDatabase().Wait();
lastTime = DateTime.Now;
}
}
}
// public static void Main(string[] args) => BuildAvaloniaApp()

View file

@ -11,7 +11,16 @@ using RestSharp;
namespace FreeTubeSyncer.REST;
public class Syncer<T> where T : class, IDataModel, new()
public interface ISyncer
{
Task ReadDatabase();
Task FetchDatabase();
void HandleDatabaseChange(string dbName, string entryObject);
void Sync();
bool IsDirty();
}
public class Syncer<T> : ISyncer where T : class, IDataModel, new()
{
private List<T> _entries = new List<T>();
private RestClient _client;
@ -19,21 +28,23 @@ public class Syncer<T> where T : class, IDataModel, new()
private string _dbName;
private string _restEndpoint;
public bool IsDirty = false;
private bool _isDirty = false;
public Syncer(DBSyncWatcher watcher, string dbPath, string dbName, string restEndpoint)
{
watcher.WatchFiles[dbName] = typeof(T);
watcher.OnDatabaseChange += HandleDatabaseChange;
_client = new RestClient(new RestClientOptions("http://localhost:5183"));
_client = new RestClient(new RestClientOptions("http://192.168.1.30:5050"));
_dbPath = dbPath;
_dbName = dbName;
_restEndpoint = restEndpoint;
ReadDatabase().Wait();
FetchDatabase().Wait();
ReadDatabase().Wait();
}
private async Task ReadDatabase()
public bool IsDirty() => _isDirty;
public async Task ReadDatabase()
{
var lines = File.ReadAllLines(_dbPath);
foreach (var entry in lines)
@ -60,20 +71,26 @@ public class Syncer<T> where T : class, IDataModel, new()
}
}
private async Task FetchDatabase()
public async Task FetchDatabase()
{
var entries = await _client.GetAsync<IEnumerable<T>>(_restEndpoint);
var entries = await _client.GetAsync<List<T>>(_restEndpoint);
if (entries == null) return;
foreach (var entry in entries)
{
if (_entries.Any(x => x.EqualId(entry.Id())))
{
var data = _entries.First(x => x.EqualId(entry.Id()));
if (data.Equals(entry)) continue;
_entries.RemoveAll(x => x.EqualId(entry.Id()));
}
_entries.Add(entry);
_isDirty = true;
}
}
private async void HandleDatabaseChange(string dbName, string entryObject)
public async void HandleDatabaseChange(string dbName, string entryObject)
{
if (dbName != _dbName)
return;
@ -92,16 +109,22 @@ public class Syncer<T> where T : class, IDataModel, new()
if (entry == null) return;
entry.MarshalData(entry.Id(), entryObject);
if (_entries.Any(x => x.EqualId(entry.Id())))
{
var data = _entries.First(x => x.EqualId(entry.Id()));
if (data.Equals(entry)) return;
_entries.RemoveAll(x => x.EqualId(entry.Id()));
}
_entries.Add(entry);
await _client.PostJsonAsync<T>(_restEndpoint, entry);
IsDirty = true;
}
public void Sync()
{
if (!IsDirty)
if (!_isDirty)
return;
Console.WriteLine($"Syncing {_dbPath}...");
var json = new List<string>();
@ -109,6 +132,6 @@ public class Syncer<T> where T : class, IDataModel, new()
json.Add(entry.JsonData());
File.WriteAllLines(_dbPath, json);
Console.WriteLine($"Updated {_dbPath}.");
IsDirty = false;
_isDirty = false;
}
}