Improve USB policy responsiveness and reliability
- Reduce USB policy polling from 60s to 15s for faster response - Add retry with exponential backoff (2s, 4s, 8s) on report failures - Add APPLYING state for real-time progress bar feedback - Check if policy is already applied locally before re-applying - Fix API schema to accept APPLYING status - Update agent to v0.1.9 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
23e7cf58ae
commit
b60255fe03
6 changed files with 115 additions and 14 deletions
|
|
@ -1215,11 +1215,9 @@ async fn check_and_apply_usb_policy(base_url: &str, token: &str) {
|
|||
}
|
||||
};
|
||||
|
||||
eprintln!("[agent] Aplicando politica USB: {}", policy_str);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use crate::usb_control::{apply_usb_policy, UsbPolicy};
|
||||
use crate::usb_control::{apply_usb_policy, get_current_policy, UsbPolicy};
|
||||
|
||||
let policy = match UsbPolicy::from_str(&policy_str) {
|
||||
Some(p) => p,
|
||||
|
|
@ -1230,6 +1228,26 @@ async fn check_and_apply_usb_policy(base_url: &str, token: &str) {
|
|||
}
|
||||
};
|
||||
|
||||
// Verifica se a politica ja esta aplicada localmente
|
||||
match get_current_policy() {
|
||||
Ok(current) if current == policy => {
|
||||
eprintln!("[agent] Politica USB ja esta aplicada localmente: {}", policy_str);
|
||||
report_usb_policy_status(base_url, token, "APPLIED", None, Some(policy_str)).await;
|
||||
return;
|
||||
}
|
||||
Ok(current) => {
|
||||
eprintln!("[agent] Politica atual: {:?}, esperada: {:?}", current, policy);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[agent] Nao foi possivel ler politica atual: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("[agent] Aplicando politica USB: {}", policy_str);
|
||||
|
||||
// Reporta APPLYING para progress bar real no frontend
|
||||
report_usb_policy_status(base_url, token, "APPLYING", None, None).await;
|
||||
|
||||
match apply_usb_policy(policy) {
|
||||
Ok(result) => {
|
||||
eprintln!("[agent] Politica USB aplicada com sucesso: {:?}", result);
|
||||
|
|
@ -1265,8 +1283,38 @@ async fn report_usb_policy_status(
|
|||
current_policy,
|
||||
};
|
||||
|
||||
if let Err(e) = HTTP_CLIENT.post(&url).json(&report).send().await {
|
||||
eprintln!("[agent] Falha ao reportar status de politica USB: {e}");
|
||||
// Retry com backoff exponencial: 2s, 4s, 8s
|
||||
let delays = [2, 4, 8];
|
||||
let mut last_error = None;
|
||||
|
||||
for (attempt, delay_secs) in delays.iter().enumerate() {
|
||||
match HTTP_CLIENT.post(&url).json(&report).send().await {
|
||||
Ok(response) if response.status().is_success() => {
|
||||
if attempt > 0 {
|
||||
eprintln!("[agent] Report de politica USB enviado na tentativa {}", attempt + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Ok(response) => {
|
||||
last_error = Some(format!("HTTP {}", response.status()));
|
||||
}
|
||||
Err(e) => {
|
||||
last_error = Some(e.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if attempt < delays.len() - 1 {
|
||||
eprintln!(
|
||||
"[agent] Falha ao reportar politica USB (tentativa {}), retentando em {}s...",
|
||||
attempt + 1,
|
||||
delay_secs
|
||||
);
|
||||
tokio::time::sleep(Duration::from_secs(*delay_secs)).await;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(err) = last_error {
|
||||
eprintln!("[agent] Falha ao reportar status de politica USB apos 3 tentativas: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1344,7 +1392,7 @@ impl AgentRuntime {
|
|||
|
||||
let mut heartbeat_ticker = tokio::time::interval(Duration::from_secs(interval));
|
||||
heartbeat_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
let mut usb_ticker = tokio::time::interval(Duration::from_secs(60));
|
||||
let mut usb_ticker = tokio::time::interval(Duration::from_secs(15));
|
||||
usb_ticker.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
|
||||
loop {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "Raven",
|
||||
"version": "0.1.6",
|
||||
"version": "0.1.9",
|
||||
"identifier": "br.com.esdrasrenan.sistemadechamados",
|
||||
"build": {
|
||||
"beforeDevCommand": "bun run dev",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ function hashToken(token: string) {
|
|||
export const USB_POLICY_VALUES = ["ALLOW", "BLOCK_ALL", "READONLY"] as const
|
||||
export type UsbPolicyValue = (typeof USB_POLICY_VALUES)[number]
|
||||
|
||||
export const USB_POLICY_STATUS = ["PENDING", "APPLIED", "FAILED"] as const
|
||||
export const USB_POLICY_STATUS = ["PENDING", "APPLYING", "APPLIED", "FAILED"] as const
|
||||
export type UsbPolicyStatus = (typeof USB_POLICY_STATUS)[number]
|
||||
|
||||
export const setUsbPolicy = mutation({
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const getPolicySchema = z.object({
|
|||
|
||||
const reportStatusSchema = z.object({
|
||||
machineToken: z.string().min(1),
|
||||
status: z.enum(["PENDING", "APPLIED", "FAILED"]),
|
||||
status: z.enum(["PENDING", "APPLYING", "APPLIED", "FAILED"]),
|
||||
error: z.string().optional(),
|
||||
currentPolicy: z.string().optional(),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4622,7 +4622,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) {
|
|||
return (
|
||||
<li key={`gpu-${idx}`}>
|
||||
<span className="font-medium text-foreground">{name ?? "Adaptador de vídeo"}</span>
|
||||
{memoryBytes ? <span className="ml-1 text-muted-foreground">VRAM {formatBytes(memoryBytes)}</span> : null}
|
||||
{memoryBytes ? <span className="ml-1 text-muted-foreground">{formatBytes(memoryBytes)} VRAM</span> : null}
|
||||
{vendor ? <span className="ml-1 text-muted-foreground">· {vendor}</span> : null}
|
||||
{driver ? <span className="ml-1 text-muted-foreground">· Driver {driver}</span> : null}
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -73,6 +73,13 @@ function getStatusBadge(status: string | undefined | null) {
|
|||
Pendente
|
||||
</Badge>
|
||||
)
|
||||
case "APPLYING":
|
||||
return (
|
||||
<Badge variant="outline" className="gap-1 border-blue-200 bg-blue-50 text-blue-700">
|
||||
<Loader2 className="size-3 animate-spin" />
|
||||
Aplicando
|
||||
</Badge>
|
||||
)
|
||||
case "APPLIED":
|
||||
return (
|
||||
<Badge variant="outline" className="gap-1 border-emerald-200 bg-emerald-50 text-emerald-700">
|
||||
|
|
@ -92,6 +99,36 @@ function getStatusBadge(status: string | undefined | null) {
|
|||
}
|
||||
}
|
||||
|
||||
function getProgressValue(status: string | undefined | null): number {
|
||||
switch (status) {
|
||||
case "PENDING":
|
||||
return 33
|
||||
case "APPLYING":
|
||||
return 66
|
||||
case "APPLIED":
|
||||
return 100
|
||||
case "FAILED":
|
||||
return 100
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
function getProgressColor(status: string | undefined | null): string {
|
||||
switch (status) {
|
||||
case "PENDING":
|
||||
return "bg-amber-500"
|
||||
case "APPLYING":
|
||||
return "bg-blue-500"
|
||||
case "APPLIED":
|
||||
return "bg-emerald-500"
|
||||
case "FAILED":
|
||||
return "bg-red-500"
|
||||
default:
|
||||
return "bg-neutral-300"
|
||||
}
|
||||
}
|
||||
|
||||
interface UsbPolicyControlProps {
|
||||
machineId: string
|
||||
machineName?: string
|
||||
|
|
@ -168,11 +205,27 @@ export function UsbPolicyControl({
|
|||
|
||||
const content = (
|
||||
<div className="space-y-4">
|
||||
{/* Status atual no topo */}
|
||||
{/* Status atual com progress bar real */}
|
||||
{usbPolicy?.status && (
|
||||
<div className="flex items-center justify-between rounded-lg border bg-slate-50 p-3">
|
||||
<span className="text-sm font-medium text-slate-600">Status da política</span>
|
||||
{getStatusBadge(usbPolicy.status)}
|
||||
<div className="space-y-2 rounded-lg border bg-slate-50 p-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm font-medium text-slate-600">Status da política</span>
|
||||
{getStatusBadge(usbPolicy.status)}
|
||||
</div>
|
||||
{/* Progress bar real baseada no estado */}
|
||||
{(usbPolicy.status === "PENDING" || usbPolicy.status === "APPLYING") && (
|
||||
<div className="space-y-1">
|
||||
<div className="h-2 w-full overflow-hidden rounded-full bg-slate-200">
|
||||
<div
|
||||
className={`h-full transition-all duration-500 ease-out ${getProgressColor(usbPolicy.status)}`}
|
||||
style={{ width: `${getProgressValue(usbPolicy.status)}%` }}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{usbPolicy.status === "PENDING" ? "Aguardando agente..." : "Agente aplicando política..."}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue