mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-18 19:30:27 +08:00
Provide a sync_status store
The `sync_status` would update every 10 seconds with the latest state of all repos, to be displayed in the repo where needed.
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
mod commands;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use tauri::{Emitter, Manager};
|
||||
|
||||
use radicle::cob::cache::COBS_DB_FILE;
|
||||
use radicle::node::{Handle, NOTIFICATIONS_DB_FILE};
|
||||
use radicle::Node;
|
||||
use radicle::identity::RepoId;
|
||||
use radicle::node::{Handle, Node, NOTIFICATIONS_DB_FILE};
|
||||
use radicle::storage::ReadStorage;
|
||||
|
||||
use radicle_types::domain;
|
||||
use radicle_types::error::Error;
|
||||
@@ -34,6 +37,8 @@ pub fn run() {
|
||||
hint: "Could not load radicle profile",
|
||||
}),
|
||||
}?;
|
||||
let public_key = profile.public_key;
|
||||
let repositories = profile.storage.repositories()?;
|
||||
|
||||
let inbox_db = radicle_types::outbound::sqlite::Sqlite::reader(
|
||||
profile.node().join(NOTIFICATIONS_DB_FILE),
|
||||
@@ -46,9 +51,11 @@ pub fn run() {
|
||||
|
||||
let events_handler = app.handle().clone();
|
||||
let node_handler = app.handle().clone();
|
||||
let seed_handler = app.handle().clone();
|
||||
|
||||
let node = Node::new(profile.socket());
|
||||
let node_status = node.clone();
|
||||
let mut node_seeds = node.clone();
|
||||
|
||||
app.manage(inbox_service);
|
||||
app.manage(patch_service);
|
||||
@@ -61,6 +68,29 @@ pub fn run() {
|
||||
}
|
||||
});
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
loop {
|
||||
let mut sync_status =
|
||||
BTreeMap::<RepoId, Option<radicle_types::cobs::repo::SyncStatus>>::new();
|
||||
for repo in &repositories {
|
||||
if let Ok(seeds) = node_seeds.seeds(repo.rid).map(Into::<Vec<_>>::into) {
|
||||
if let Some(status) = seeds.iter().find_map(
|
||||
|radicle::node::Seed { nid, sync, .. }| {
|
||||
(*nid == public_key).then_some(sync.clone())
|
||||
},
|
||||
) {
|
||||
sync_status.insert(repo.rid, status.map(Into::into));
|
||||
} else {
|
||||
// The local node wasn't found in the seed nodes table.
|
||||
sync_status.insert(repo.rid, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = seed_handler.emit("sync_status", sync_status);
|
||||
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
|
||||
}
|
||||
});
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
loop {
|
||||
if node.is_running() {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { SyncedAt } from "./SyncedAt";
|
||||
|
||||
export type SyncStatus = {
|
||||
"status": "synced";
|
||||
/**
|
||||
* At what ref was the remote synced at.
|
||||
*/
|
||||
at: SyncedAt;
|
||||
} | {
|
||||
"status": "outOfSync";
|
||||
/**
|
||||
* Local head of our `rad/sigrefs`.
|
||||
*/
|
||||
local: SyncedAt;
|
||||
/**
|
||||
* Remote head of our `rad/sigrefs`.
|
||||
*/
|
||||
remote: SyncedAt;
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
/**
|
||||
* Holds an oid and timestamp.
|
||||
*/
|
||||
export type SyncedAt = { oid: string; timestamp: number };
|
||||
@@ -7,6 +7,7 @@ use radicle::node::{Alias, AliasStore};
|
||||
|
||||
pub mod diff;
|
||||
pub mod issue;
|
||||
pub mod repo;
|
||||
pub mod stream;
|
||||
pub mod thread;
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
use localtime::LocalTime;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize, ts_rs::TS)]
|
||||
#[serde(tag = "status")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "repo/")]
|
||||
pub enum SyncStatus {
|
||||
/// We're in sync.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Synced {
|
||||
/// At what ref was the remote synced at.
|
||||
at: SyncedAt,
|
||||
},
|
||||
/// We're out of sync.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
OutOfSync {
|
||||
/// Local head of our `rad/sigrefs`.
|
||||
local: SyncedAt,
|
||||
/// Remote head of our `rad/sigrefs`.
|
||||
remote: SyncedAt,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<radicle::node::SyncStatus> for SyncStatus {
|
||||
fn from(value: radicle::node::SyncStatus) -> Self {
|
||||
match value {
|
||||
radicle::node::SyncStatus::Synced { at } => SyncStatus::Synced { at: at.into() },
|
||||
radicle::node::SyncStatus::OutOfSync { local, remote } => SyncStatus::OutOfSync {
|
||||
local: local.into(),
|
||||
remote: remote.into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds an oid and timestamp.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, ts_rs::TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export)]
|
||||
#[ts(export_to = "repo/")]
|
||||
pub struct SyncedAt {
|
||||
#[ts(as = "String")]
|
||||
pub oid: radicle::git::Oid,
|
||||
#[serde(with = "radicle::serde_ext::localtime::time")]
|
||||
#[ts(type = "number")]
|
||||
pub timestamp: LocalTime,
|
||||
}
|
||||
|
||||
impl From<radicle::node::SyncedAt> for SyncedAt {
|
||||
fn from(value: radicle::node::SyncedAt) -> Self {
|
||||
Self {
|
||||
oid: value.oid,
|
||||
timestamp: value.timestamp,
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -1,13 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import type { SyncStatus } from "@bindings/repo/SyncStatus";
|
||||
|
||||
import { SvelteMap } from "svelte/reactivity";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
|
||||
import { invoke } from "@app/lib/invoke";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
|
||||
import * as router from "@app/lib/router";
|
||||
import { nodeRunning } from "@app/lib/events";
|
||||
import { nodeRunning, syncStatus } from "@app/lib/events";
|
||||
import { theme } from "@app/components/ThemeSwitch.svelte";
|
||||
import { unreachable } from "@app/lib/utils";
|
||||
|
||||
@@ -25,6 +27,7 @@
|
||||
|
||||
let unlistenEvents: UnlistenFn | undefined = undefined;
|
||||
let unlistenNodeEvents: UnlistenFn | undefined = undefined;
|
||||
let unlistenSyncStatus: UnlistenFn | undefined = undefined;
|
||||
|
||||
onMount(async () => {
|
||||
if (window.__TAURI_INTERNALS__) {
|
||||
@@ -32,6 +35,13 @@
|
||||
// Add handler for incoming events
|
||||
});
|
||||
|
||||
unlistenSyncStatus = await listen<Record<string, SyncStatus>>(
|
||||
"sync_status",
|
||||
event => {
|
||||
syncStatus.set(new SvelteMap(Object.entries(event.payload)));
|
||||
},
|
||||
);
|
||||
|
||||
unlistenNodeEvents = await listen<boolean>("node_running", event => {
|
||||
nodeRunning.set(event.payload);
|
||||
});
|
||||
@@ -61,6 +71,9 @@
|
||||
if (unlistenEvents) {
|
||||
unlistenEvents();
|
||||
}
|
||||
if (unlistenSyncStatus) {
|
||||
unlistenSyncStatus();
|
||||
}
|
||||
if (unlistenNodeEvents) {
|
||||
unlistenNodeEvents();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
import type { SyncStatus } from "@bindings/repo/SyncStatus";
|
||||
|
||||
import { SvelteMap } from "svelte/reactivity";
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export const nodeRunning = writable<boolean>(false);
|
||||
export const syncStatus = writable<SvelteMap<string, SyncStatus>>(
|
||||
new SvelteMap(),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user