lock sync dir access

This commit is contained in:
mbecker20
2024-06-07 22:02:58 -07:00
parent 078ba59002
commit 6aa801b705
3 changed files with 78 additions and 4 deletions

View File

@@ -6,7 +6,7 @@ use monitor_client::entities::{
update::Log, CloneArgs, LatestCommit,
};
use crate::config::core_config;
use crate::{config::core_config, state::resource_sync_lock_cache};
pub async fn get_remote_resources(
sync: &ResourceSync,
@@ -37,6 +37,12 @@ pub async fn get_remote_resources(
fs::create_dir_all(&config.sync_directory)
.context("failed to create sync directory")?;
// lock simultaneous access to same directory
let lock = resource_sync_lock_cache()
.get_or_insert_default(&sync.id)
.await;
let _lock = lock.lock().await;
let mut logs =
git::clone(clone_args, &config.sync_directory, github_token)
.await

View File

@@ -5,7 +5,7 @@ use monitor_client::entities::{
procedure::ProcedureState, repo::RepoState,
sync::ResourceSyncState,
};
use tokio::sync::OnceCell;
use tokio::sync::{Mutex, OnceCell};
use crate::{
auth::jwt::JwtClient,
@@ -99,3 +99,11 @@ pub fn resource_sync_state_cache() -> &'static ResourceSyncStateCache
OnceLock::new();
RESOURCE_SYNC_STATE_CACHE.get_or_init(Default::default)
}
pub type ResourceSyncLockCache = Cache<String, Arc<Mutex<()>>>;
pub fn resource_sync_lock_cache() -> &'static ResourceSyncLockCache {
static RESOURCE_SYNC_LOCK_CACHE: OnceLock<ResourceSyncLockCache> =
OnceLock::new();
RESOURCE_SYNC_LOCK_CACHE.get_or_init(Default::default)
}

View File

@@ -1,6 +1,12 @@
import { useRead } from "@lib/hooks";
import { RequiredResourceComponents } from "@types";
import { Card, CardDescription, CardHeader, CardTitle } from "@ui/card";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@ui/card";
import { FolderSync } from "lucide-react";
import { Link } from "react-router-dom";
import { DeleteResource, NewResource } from "../common";
@@ -10,14 +16,32 @@ import { ResourceSyncConfig } from "./config";
import { useState } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ui/tabs";
import { ExecuteSync, RefreshSync } from "./actions";
import { sanitizeOnlySpan, sync_no_changes } from "@lib/utils";
import { Section } from "@components/layouts";
const useResourceSync = (id?: string) =>
useRead("ListResourceSyncs", {}).data?.find((d) => d.id === id);
const PENDING_TYPE_KEYS: Array<[string, string]> = [
["Server", "server_updates"],
["Deployment", "deployment_updates"],
["Build", "build_updates"],
["Repo", "repo_updates"],
["Procedure", "procedure_updates"],
["Alerter", "alerter_updates"],
["Builder", "builder_updates"],
["Server Template", "server_template_updates"],
["Resource Sync", "resource_sync_updates"],
["Variable", "variable_updates"],
["User Group", "user_group_updates"],
];
const PendingOrConfig = ({ id }: { id: string }) => {
const [view, setView] = useState("Pending");
const pendingDisabled = true;
const sync = useRead("GetResourceSync", { sync: id }).data;
const pendingDisabled = !sync || sync_no_changes(sync);
const currentView = view === "Pending" && pendingDisabled ? "Config" : view;
const tabsList = (
@@ -35,10 +59,46 @@ const PendingOrConfig = ({ id }: { id: string }) => {
<TabsContent value="Config">
<ResourceSyncConfig id={id} titleOther={tabsList} />
</TabsContent>
<TabsContent value="Pending">
<Section titleOther={tabsList}>
{PENDING_TYPE_KEYS.map(([type, key]) => (
<PendingView
key={type}
type={type}
log={sync?.info?.pending?.[key]}
/>
))}
</Section>
</TabsContent>
</Tabs>
);
};
const PendingView = ({
type,
log,
}: {
type: string;
log: string | undefined;
}) => {
if (!log) return;
return (
<Card>
<CardHeader className="flex-col">
<CardTitle>{type} Updates</CardTitle>
</CardHeader>
<CardContent>
<pre
dangerouslySetInnerHTML={{
__html: sanitizeOnlySpan(log),
}}
/>
</CardContent>
</Card>
);
};
export const ResourceSyncComponents: RequiredResourceComponents = {
list_item: (id) => useResourceSync(id),