Salta al contenuto

Blog ·

Un filo da trascinare, e esattamente un innesco

Trascinare un filo è la parte facile. Il difficile era cosa può toccare un pulsante di prova, chi agisce quando nessuno guarda e quanto può durare una pausa.

Di Provibr

I nostri flussi di automazione sono nati come elenco di passi, sono diventati un grafo, poi una tela, e in questo giro hanno finalmente ricevuto il gesto che tutti immaginano sentendo «editor di flussi»: si afferra il punto a destra di un nodo e si tira un filo fino al punto a sinistra di un altro.

Quel gesto è una manciata di righe di codice e un lungo commento che spiega perché quelle righe stanno dove stanno. Il resto del giro è stato fatto di domande che con il trascinamento non hanno nulla a che vedere. Quanti posti possono avviare un flusso. Cosa può toccare un pulsante di prova. Chi agisce quando nessuno guarda. E quanto può durare la pausa di un passo.

La cattura che si mangia il clic

La tela ha un solo strato di trasformazione. I nodi vi stanno in posizione assoluta e i fili sono un SVG in quello stesso strato, quindi non esiste un secondo sistema di coordinate che possa sfasarsi dal primo. Quella parte è noiosa di proposito.

La parte interessante è la cattura del puntatore. Quando si preme su un punto di uscita, qualcosa deve seguire il puntatore fino al rilascio, anche fuori dalla finestra. L’implementazione ovvia cattura sul punto premuto, ed è sbagliata in un modo che non produce alcun errore.

La cattura reindirizza ogni evento di puntatore successivo all’elemento che cattura, pointerup compreso, e il browser attiva poi click sull’antenato comune della pressione e del rilascio. Se cattura il punto stesso, un trascinamento che finisce su un altro punto lì non arriva mai; torna dov’era partito. Cattura quindi la superficie, e dove il dito si sia davvero staccato è una domanda a parte, cui risponde document.elementFromPoint().

Quella risposta ha tre gradini. Un punto di ingresso sotto il cursore. Altrimenti una scatola di nodo sotto il cursore, che porta al suo primo ingresso. Altrimenti una calamita: l’ingresso più vicino entro sedici pixel di schermo, ed è ciò che rende il gesto indulgente senza costringere nessuno a centrare un bersaglio di dieci pixel.

Due ritrovamenti minori, che compaiono solo costruendolo. React aggancia wheel in modo passivo alla radice, quindi impedire l’azione predefinita nel suo gestore non fa nulla e la pagina scorre mentre si prova a ingrandire; quell’ascoltatore va posto sull’elemento stesso, esplicitamente non passivo. E il punto medio di una curva di Bézier non è il centro del suo riquadro di ingombro: colpire un filo significa quindi chiedere al tracciato un punto a una certa lunghezza e passarlo per la matrice di trasformazione corrente.

Clic e poi clic funziona ancora. Non è la via minore: è la via che funziona con la tastiera, e per questo i punti sono rimasti pulsanti veri.

Un innesco, e quattro cose che vi pendono

Un grafo ha esattamente un nodo di innesco. Zero è un errore al salvataggio e due è un errore al salvataggio. Sembra ordine. È portante, e quattro funzioni vi poggiano sopra.

Cosa dàPerché serve un solo innesco
La raggiungibilitàOgni nodo eseguibile deve essere raggiungibile da un unico punto di partenza noto
Il rilevamento dei cicliUna visita in profondità con marcatura a colori richiede una radice; due radici sono due visite e due risposte da fondere
Il selettore di variabiliQuali variabili esistono dipende dall’evento scattato, e un secondo innesco sarebbero due risposte in un solo editor
La potatura del contestoUn gruppo di variabili che questo evento non può fornire viene rimosso: leggerlo è quindi un errore e non una stringa vuota

L’ultima riga si ripaga da sola. Gli eventi di innesco sono quattro: un server fornito, reinstallato, eliminato oppure avviato a mano. Un server eliminato non ha un identificativo di sistema operativo, quindi l’intero gruppo del sistema operativo sparisce dal contesto invece di essere messo a oggetto vuoto. Con variabili rigorose, leggerlo produce allora un errore leggibile «variabile sconosciuta» nel momento del salvataggio. Se invece lo si svuota, la condizione che lo legge diventa falsa, in silenzio, per sempre, sul ramo che contava.

È anche il motivo per cui non esiste un nodo di iniezione a parte. L’avvio manuale è un evento di innesco e non un secondo ingresso; aggiungerne uno romperebbe l’invariante su cui poggiano tutte e quattro le funzioni, in cambio di un nodo che si disegna un po’ meglio.

Una prova non tocca nulla, e percorre lo stesso

L’editor ha un pulsante Test run, e un grafo può ora contenere un nodo che avvia, ferma, spegne, sospende o riprende il server di quell’esecuzione. Questi due fatti sulla stessa schermata sono una trappola: qualcuno premerà prova per vedere quale ramo prende un grafo, e spegnerà una macchina di un cliente.

Una prova non invia quindi mai un comando. Il nodo di azione torna subito, marcato come saltato, con un codice di motivo reso nella lingua di chi legge. E soprattutto: prende il ramo ok. Una prova che cadesse sul ramo di errore sosterrebbe che il grafo fa qualcosa che non fa, ed è peggio che non dire nulla. Agire davvero passa per l’iniezione, che è un’esecuzione reale e chiede una conferma.

Chi agisce quando nessuno guarda

Un’esecuzione di flusso non ha spettatori. In un ordine, chi ha premuto Ordina è al più per caso la persona a cui attribuire l’azione. In una cancellazione può già essere andata via. Ma trovare un server richiede un attore con un profilo di permessi, e quel profilo deve venire da qualche parte.

La scelta è che un’esecuzione agisce come la persona proprietaria dell’account, per tre motivi in ordine di peso. Il momento dell’autorizzazione è il rilascio e non l’esecuzione: salvare un flusso richiede il modulo degli script, appenderlo a un piano richiede permessi sui piani, ed è la stessa forma di un’attività pianificata o del lavoratore di sorveglianza. Agire come chi ha premuto renderebbe il grafo non riproducibile: lo stesso flusso avvierebbe una macchina per un acquirente e non per un altro, per una casella di permessi che con il flusso non c’entra nulla. E il confine vero resta comunque duro: la ricerca riceve l’identificativo di organizzazione dell’esecuzione e rifiuta ogni riga fuori da esso, e questo nodo può per costruzione indirizzare solo il server di questa esecuzione.

Prima che nasca un comando, due setacci devono dire di sì entrambi: questo fornitore sa fare questo comando, e questo tipo di risorsa lo può. Su Proxmox oggi nessuna delle cinque azioni viene rifiutata su un contenitore, ed è proprio per questo che la prova da capo a fondo chiede anche un ampliamento di disco e pretende che quello venga rifiutato. Un setaccio che non dice mai di no è indistinguibile da un setaccio non collegato.

Cinque minuti, perché la pausa sta dentro una richiesta

Il nodo di ritardo ammette da cinque a trecento secondi. L’incarico chiedeva seicento, e seicento è sbagliato per un motivo misurabile: un flusso innescato da un ordine viene atteso dentro la richiesta dell’ordine. Dieci minuti di pausa sono dieci minuti in cui un cliente che paga guarda un indicatore di caricamento.

Non esiste uno stato di attesa duraturo, e finché non esiste una pausa non può sopravvivere a una richiesta. Quella giuntura porta un nome nel codice, così che «perché il mio flusso non può aspettare un’ora» sia una domanda con una risposta rintracciabile. Richiede una coda capace di conservare un’esecuzione a metà e riprenderla più tardi, e solo quando esisterà si potranno prendere in considerazione i cicli.

Il nodo HTTP, e perché non è fetch

Un nodo HTTP in uno strumento di automazione è una macchina per la falsificazione di richieste lato server se non si sta attenti, e starci attenti esclude qui il client standard.

fetch non sa fare l’unica cosa che questa politica richiede: collegarsi a un indirizzo scelto da noi mentre il nome host resta in Host e in SNI. Risolve per conto suo, e quella seconda risoluzione è esattamente la finestra in cui vive il riassegnamento DNS. Si setaccia un indirizzo pubblico e mezzo secondo dopo il client si collega al ciclo locale perché la durata del record era zero.

Il client HTTP di Node accetta una risoluzione propria, e la nostra restituisce esattamente un indirizzo: quello approvato dal setaccio. Host e SNI restano derivati dal nome host, quindi TLS viene validato contro il nome. La verifica del certificato è attiva senza interruttore per spegnerla, e le variabili d’ambiente di proxy non fanno nulla, perché quel client non le legge.

I reindirizzamenti si seguono a mano, al massimo tre, e ogni salto viene risetacciato da capo: schema, informazione utente, porta, DNS, ogni indirizzo. Un reindirizzamento aperto verso un punto di metadati di una nuvola viene rifiutato al secondo salto, anche se il primo era un host pubblico rispettabile. Sono ammessi sette nomi di intestazione, e due di essi possono portare solo un riferimento a un segreto conservato, decifrato per la richiesta, oscurato in tutto ciò che viene salvato e registrato solo per nome.

Cosa annoteremmo

  1. Catturi sull’involucro, non su ciò che ha afferrato. La cattura del puntatore reindirizza tutto ciò che segue, e il sintomo è un gesto che finisce in silenzio dov’era partito.
  2. Un gesto indulgente richiede una catena di ripieghi, non un bersaglio più grande. Elemento sotto il cursore, poi il suo genitore, poi una soglia di distanza.
  3. Un solo ingresso compra quattro funzioni. Raggiungibilità, rilevamento dei cicli, selettore di variabili e potatura del contesto richiedono tutti e quattro una radice nota. Conti cosa perde prima di aggiungerne un secondo.
  4. Rimuova ciò che non può esistere; non lo svuoti. Un gruppo di variabili assente fallisce ad alta voce al salvataggio; uno vuoto fallisce in silenzio durante l’esecuzione.
  5. Un pulsante di prova capace di toccare la produzione non è un pulsante di prova. Saltare e prendere comunque il ramo di successo è la combinazione onesta.
  6. Una pausa è limitata da chi la attende. Se il chiamante è una richiesta HTTP, la pausa si conta in secondi.

Per chiarezza su cosa sia tutto questo: i flussi sono raggiungibili dalla schermata degli script e la tela è ormai l’unico editor. Tre cose non sono dimostrate. L’attesa di un comando davvero concluso non è stata misurata contro un ipervisore reale, il trascinamento è stato guidato con eventi simulati del protocollo del browser e non con una mano, e nulla di tutto ciò è stato misurato su una compilazione di produzione.

Dal lavoro di piattaforma di Provibr. Perché il grafo debba anzitutto essere finito è spiegato in un flusso è un grafo, e un grafo dev’essere finito, e come una schermata di sintesi legga le tabelle altrui senza mai scriverci è spiegato in proiettare, mai sostituire.

Inizi con un host e un agente

Crei un account, installi l’agente con un solo comando e colleghi il suo primo host Proxmox. Il periodo di prova dura 14 giorni e non chiede alcun dato di pagamento.