FileSync2 protokol
Da vi efterhånden må indrømme at FTP-protokollen ikke er velegnet til generel filsynkronisering, ud fra følgende betragninger:
Protokollen er uegnet til at søge efter ændringer i en stor mængde filer.
Protokollen er inkonsekvent mht. tegnsæt og lign., hvilket leder til synkroniseringsproblemer.
Protokollen er langsom.
Protokollen er usikker.
…så har vi besluttet at skabe en ny komponent til dette.
Målsætning
Målsætningen med den nye filsynk er følgende:
Stabil. I dag er der alt for mange problemer med synkroniseringerne.
Platformsuafhængig. Vi vil gerne vedblive med at holde en vis platformsuafhængighed.
Hurtigere. Vi vil gerne minimere tiden imellem en ændring i filer (på begge sider) og hvornår dette reflekteres.
Low-impact. Integrationen i dag er tung på systemet, da den hele tiden gennemgår hele strukturen. Den nye integration skal kunne operere på changedate/time, således at vi kun betragter ting som er ændret.
Overordnede guidelines
Den nye komponent består af et lokalt stykke software, som installeres på den maskine der skal synkronisere og som herefter kommunikerer direkte med Microbizz. Det forventes at dette sker via et specieldesignet interface og ikke via Microbizz' API.
Komponentens ansvar bliver primært at holde øje med ændringer på lokalmaskinen og svare på forespørgsler fra Microbizz. Microbizz er derfor ansvarlig for at håndtere logikken omkring hvad som er ændret, og initiere de nødvendige overførsler.
Komponenten og filserveren
På kundens filserver afsættes en folder som Microbizz' synkroniseringsområde. Det forventes at Microbizz bygger sine grundlæggende foldere under denne struktur, og at der ikke er andre filer i denne struktur. På en Windows-maskine kunne en evt. placering være C:\MB-FILER\
Det er kun komponenten der kender denne placering. Når komponenten taler med Microbizz, så tales der altid i den underliggende struktur, dvs. hvis komponenten og Microbizz kommunikerer om folderen /todo/Ventu/Opgave (1), så er dette underforstået som C:\MB-FILER\todo\Ventu\Opgave (1) i ovenstående eksempel.
Komponenten skal designes på en måde som er platformsuafhængig. I den forbindelse er NodeJS blevet foreslået.
Komponenten skal kunne konfigureres, enten via et interface eller via en konfigurationsfil. Komponenten skal kende synkroniseringsfolderen (som ovenfor), samt de login-oplysninger den har brug for, for at kunne kommunikere med Microbizz, hvilket f.eks. kunne fastsættes til at være et sæt brugeroplysninger, herunder kontraktnummer, brugernavn og kodeord. Alternativt kunne skabes en nøgle ala API-nøglen (men det må ikke være den, da den i princippet er offentlig).
Det er vigtigt at det er komponenten der forbinder til Microbizz og ikke omvendt, da det minimerer de netværksudfordringer der kan opstå. Omvendt så har Microbizz behov for at skulle kunne sende kommandoer til komponenten med meget kort varsel (f.eks. hvis der skal hentes en proxy-fil), så enten skal komponenten polle Microbizz med meget korte mellemrum, eller også skal der etableres en permanent forbindelse.
Generel forventing til funktionalitet
Det skal fra Microbizz være mulighed for at udløse en test, der på en brugervenlig måde afgør om komponenten har forbindelse til Microbizz og, om den kan skrive/læse på den server hvor den er installeret.
Det skal være muligt at deaktivere komponenten på en “pæn” måde, dvs. at hvis den agerer proxy, så skal den sørge for at trække alle filer tilbage på serveren.
Komponenten
Komponenten skal kunne understøtte en række kommandoer:
Fortæl om ændringer i strukturen
Komponenten skal kunne berette om alle ændringer i filstrukturen siden sidst, herunder filer som er ændret, filer som er nyoprettede og filer som er slettede. Især det sidste kan evt. være tricky.
Nulstil ændringer i strukturen
Microbizz skal kunne kvittere for at have set ændringer i strukturen, hvilket vil nulstille ændringer i strukturen, forstået på den måde at når dette kald modtages, så vil et efterfølgende kald til at fortælle om ændringer i strukturen resultere i et tomt resultat, med mindre der er sket nye ændringer.
Modtag fil
Komponenten skal kunne modtage en fil og blive bedt om at gemme denne i en specifik folder. Såfremt folderen ikke eksisterer, så oprettes denne automatisk.
Send fil
Komponenten skal ligeledes kunne sende en fil fra en specifik lokation.
Slet fil
Komponenten skal kunne slette en fil fra en specifik lokation, selv om vi sikkert ikke vil anvende dette i første udkast. Som en mellemløsning, kunne man også forestille sig at hvis komponenten blev bedt om at slette en fil, så omdøbte den i stedet filen til .sletmig og ignorerede filer af denne type fremover. Igen kunne dette måske styres vha. indstillinger i komponenten.
Flyt mappe
Komponenten skal kunne flytte en mappestruktur fra et sted til et andet. F.eks. skal mappen /todo/Ventu/Opgave (1) kunne bedt flyttet til /todo/Mureropgaver/Ventu/Opgave (1), hvilket skal tage alt filindhold fra den gamle mappe og flytte dette til den nye mappe.
(TODO: Håndtering af filer som er markeret som ændret/slettet i den gamle mappe).
Microbizz
Microbizz kommer til at være den aktive del i synkroniseringen, og kommer ligeledes til at være afgørende for hvor filer befinder sig på filserveren.
Rodobjektets mappe
I denne dokumentation anses et rodobjekt, som værende et objekt i Microbizz der indeholder en understruktur af filer, f.eks. en opgave eller et CRM-objekt. Et rodobjekt skal til ethvert tidspunkt kende sin sti på fjernserveren. Taler vi om en opgave, kan rodobjektet f.eks. afgøre at dets sti er /todo/Ventu/Opgave (1) hvilket så gemmes i relation til rodobjektet.
Ændring af rodobjektets mappe
Det skal være muligt (evt. først i en senere version) at kunne ændre rodobjektets mappe, men da dette også afhænger af at filerne fysisk bliver flyttet på serveren, så bliver dette nødt til at være en lidt mere kompliceret proces.
Hvis rodobjektets mappe ønskes flyttet, så gemmes den nye mappe først på rodobjektet som en ny oplysning: “Ny sti”. Dvs. at rodobjektet fra før kunne have stien /todo/Ventu/Opgave (1) og en ny sti /todo/Opgave (1) for at indikere at den ønsker at blive placeret på en ny sti.
Når filsynkroniseringen kommunikerer med komponenten, så beder den om at få flyttet strukturen /todo/Ventu/Opgave (1) over til den nye sti /todo/Opgave (1)
Hvis komponenten melder success, så er rodobjektets sti nu /todo/Opgave (1) og det har ikke længere en ny sti.
Hvis komponenten melder fejl, så beholder rodobjektet sin eksisterende sti, og den må forsøge igen senere.
Filer i Microbizz og deres endelige sti
En fil i Microbizz kender kun sin sti i forhold til rodobjektet, dvs. en fil der ligger i en mappe “Tegninger” på opgave 1, vil have stien: /Tegninger/oversigt.png
Filens endelige sti i forhold til filserveren vil derfor kunne findes ved at sammensætte rodobjektets sti med filens sti, dvs. i ovenstående eksempel vil dette blive /todo/Ventu/Opgave (1)/Tegninger/oversigt.png Denne totale sti gemmes aldrig nogle steder, men skal altid beregnes for at tage højde for at rodmappen kan flytte sig.
Sammenligning af foldere
Der gælder specielle regler om sammenligning af foldere. En folder sammenlignes led for led, og et led betragtes som ens, hvis følgende er gældende (prioriteret)
Leddet er helt enslydende i begge ender.
Leddet er ikke enslydende, men i slutningen af navnet indgår en parentes som indeholder et enslydende nummer i begge led.
Med andre ord vil det sige at følgende foldere betegnes som ens (såfremt der ikke findes en helt identisk folder):
/todo/Malerarbejde (1)/Monter en stang (29)/
og
/todo/Maler (1)/Monter en stang (29)/
men ikke ens med
/todo/Malerarbejde (2)/Monter en stang (29)/
eller
/todo/Maler (1)/Monter en stang (28)/
Denne logik skal observeres i begge ender, og kan med fordel implementeres i en frontversion, der evt. vil omskrive en fjernmappe til et passende lokalt mappenavn, inden øvrig logik anvendes.
Bemærk yderligere at i klient-enhed, så skal der også forsøges at foretage en delvis omskrivning, såfremt at en fuld omskrivning ikke kan finde sted. Dvs. at hvis klienten har en tom mappe der hedder:
/todo/Maler (1)/
og bliver bedt om at oprette en mappe der hedder:
/todo/Malerarbejde (1)/Mal hele køkkenet (139)/
…så skal klienten kunne udlede at denne mappes korrekte navn bør være og oprette den her:
/todo/Maler (1)/Mal hele køkkenet (139)/
Hentning af proxy-fil
Hvis en fil er i proxy, og der er behov for den, så kan denne simpelt hentes ved at kommunikere med komponenten og bede om at hente filen via dens endelige sti.
Synkronisering
En fuld synkronisering udføres ved at bede komponenten om at sende en liste med filer opdateret siden sidst, hvilket vil resultere i en liste med endelige stier, samt en indikator for om filer er oprettet/opdateret eller slettet. Lidt karikeret:
/todo/Ventu/Opgave (1)/Tegninger/oversigt.png | Opdateret |
/todo/Ventu/Opgave (1)/Tegninger/foto1.png | Opdateret |
/todo/Ventu/Opgave (1)/Tegninger/gammel_oversigt.png | Slettet |
/tmp/junkfil.txt | Opdateret |
Herefter skaber Microbizz en tilsvarende liste for sine egne filer, dvs. endelige stier, samt indikatoren:
/todo/Ventu/Opgave (1)/Tegninger/foto1.png | Opdateret |
/todo/Ventu/Opgave (1)/Tilbud/tilbud29.doc | Slettet |
Logisk set merger Microbizz herefter disse to lister med den endelige sti som nøgle:
Endelig sti | Komponent status | Microbizz status |
---|---|---|
/todo/Ventu/Opgave (1)/Tegninger/oversigt.png | Opdateret | |
/todo/Ventu/Opgave (1)/Tegninger/foto1.png | Opdateret | Opdateret |
/todo/Ventu/Opgave (1)/Tilbud/tilbud29.doc | Slettet | |
/todo/Ventu/Opgave (1)/Tegninger/gammel_oversigt.png | Slettet | |
/tmp/junkfil.txt | Opdateret |
I det første tilfælde er der tale om en fil der er opdateret på filserveren, enten fordi den er nyoprettet eller fordi den er opdateret. Da Microbizz ikke har data på denne fil, så vil Microbizz starte med at se om den kan finde et rodobjekt der har en sti der svarer til den endelige sti. Her finder den Opgave 1, hvor den hurtigt kan gå ind og opdatere eller oprette filen.
I næste tilfælde, så er der tale om en fil der er opdateret i begge ender. I dette tilfælde må der være en indstilling der afgør hvilken side som har prioritet. Hvis det er Microbizz, vil komponenten blive bedt om at gemme Microbizz' kopi af filen og hvis det er filserveren, så vil Microbizz opdatere sin egen kopi af filen.
Den tredje fil rapporterer Microbizz som slettet siden sidst, og derfor bliver komponenten bedt om at slette filen på filserveren.
Den fjerde fil er lige omvendt. Her ser Microbizz om vi har et passende rodobjekt og sletter herefter en matchende fil, såfremt vi har den.
Den sidste fil er medtaget som et eksempel på en fil, som er blevet lagt ind i filstrukturen uden at Microbizz kender til den. Her vil Microbizz prøve at se om der er et rodobjekt der modsvarer folderen /tmp. Da dette ikke lykkedes, så ignorerer den blot filen.
Når hele processen er kørt igennem notificeres komponenten om at alle ændringer nu er registreret i Microbizz. (TODO: Hvad med ændringer under synkroniseringen) og Microbizz sørger ligeledes for at nulstille sin registrering af ændringer.
Bemærk: Det skal vel være tilladt for kunden at ændre navnene på mapper og undermapper, med visse forbehold. Kunden kan f.eks. omdøbe /todo/Ventu/Opgave (1) til /todo/Ventu/MinOpgave (1), og Microbizz skal så kunne finde ud af at der er tale om en omdøbning.
Protokol
Alle multi-byteværdier er kodet så første byte er højest.
Strenge er kodet i UTF-8.
Foldere er med startende og afsluttende / dvs. en folder kan være /todo/Ventu/MinOpgave_1/
Filnavne starter med / dvs. en fil kan være /todo/Ventu/MinOpgave_1/info.txt
Handshake
Når en klient forbinder til filserver-komponenten, så sender den følgende sekvens:
Bytes | Indhold |
---|---|
10 | Fast tekst: “MBFILESYNC” |
5 | Versionsnummer af protokol. 5 cifre, f.eks. 00001, se versioner |
4 | Kontraktnummer, som ønskes synkroniseret f.eks. 2345 |
29 | API-nøglen der hører til kontraktnummeret |
Serveren svarer herefter enten:
Bytes | Indhold |
---|---|
4 | Returkode, “OKOK”. |
eller:
Bytes | Indhold |
---|---|
4 | Returkode, “FAIL” for at indikere at noget gik galt. |
250 | En evt. fejlmeddelelse |
Serveren svarer “OKOK” hvis den kan håndtere den angivne protokol, og hvis den kan finde en matchende kontrakt, med tilhørende API-nøgle. Hvis serveren rapporterer “FAIL”, så afbryder den efterfølgende forbindelsen.
Generel kommunikation
Efterfølgende kommunikation sker vha. pakker der altid ser ud som følger:
Bytes | Indhold |
---|---|
5 | Pakketype. Angiver indholdet af pakken. |
4 | 32 bit der angiver løbenummer på pakken. |
8 | 64 bit der angiver størrelsen på payloaden. |
X | Payload, som afhænger af pakketypen. |
Løbenummeret er et fortløbende nummer som starter med 1 i hver session og tæller op for hvert stykke efterfølgende kommunikation. Hvis der svares på en forespørgsel, så skal svaret have samme løbenummer som forespørgslen. På den måde kan serveren sammenholde forespørgsel og svar. Hvis det fremgår nedenfor at der ikke er et payload, så vil størrelsen på payloaden blive angivet som 0 og dermed følger ingen payloadbytes.
Pakker
RQCHG
Denne anmodning går fra serveren til klienten og er en forespørgsel om at få en liste over ændringer siden sidst. Payloaden er en JSON-struktur der beskriver hvornår "siden sidst" er, og også beskriver hvor meget data serveren anslår der mangler at blive overført til klienten:
Felt | Type | Indhold |
---|---|---|
date | string | Dato på formattet YYYY-MM-DD. Kan være tom, hvilket betyder: Giv mig alle ændringer. |
time | string | Klokkeslet på formattet HH:MM:SS. Hvis date er tom, skal time også være tom og vice versa. |
filesleft | int | Cirka antal filer som mangler at blive overført fra server til klient; kun hvis version er >= 00003 |
mbytesleft | int | Cirka antal MBytes som mangler at blive overført fra server til klient; kun hvis version er >= 00003 |
ANCHG
Dette er svaret på anmodningen RQCHG, som går fra klienten til serveren. Den beskriver alle ændringer siden sidst. Payloaden er en JSON-struktur, der beskriver ændringerne. Hvis en folder er blev ændret/tilføjet/slettet, så overføres dette ligesom en fil ændring, fil stien er blot afsluttet med /. Hvis der ikke er nogen ændringer, så skal klienten enten returnere samme dato/tid som i forespørgelsen.
Felt | Type | Indhold |
---|---|---|
date | string | Dato for den nyeste ændring der optræder i listen. |
time | string | Tidspunkt for den nyeste ændring der optræder i listen. |
changes | array | Ændringer. Se nedenfor. |
Feltet "changes" indeholder en liste med ændringer; hver ændring er et array med følgende felter:
Felt | Type | Indhold |
---|---|---|
filepath | string | Fuld sti til fil/folder (inkl. evt. filnavn). |
newfilepath | string | (KUN VED MOVED) Fuld sti til destinationen fil/folder (Uden filnavn). |
newname | string | (KUN VED RENAME) Nye navn til fil/mappe |
date | string | Dato for ændring. |
time | string | Tidspunkt for ændring. |
mdate | string | Filens datostempel. |
mtime | string | Filens tidsstempel. |
size | string | Filens størrelse, i bytes. |
changetype | string | Type af ændring. MODIFIED, DELETED, MOVED og RENAMED. Nyoprettede filer, sendes også som MODIFIED |
RQFLS
Denne anmodning går fra serveren til klienten, og instruerer klienten i at serveren aldrig mere vil spørge om ændringer fra før den angivne dato. Dette kan klienten bruge til at flushe evt. interne cacher over slettede filer. Payloaden er en JSON-struktur, der benævner dato og tid.
Felt | Type | Indhold |
---|---|---|
date | string | Dato for hvornår serveren aldrig vil spørge mere. |
time | string | Tidspunkt for hvornår serveren aldrig vil spørge mere. |
RQFIL
Denne anmodning går fra serveren til klienten, og beder klienten om at transmittere en given fil. JSON-strukturen angiver præcis hvilken fil som ønskes.
Felt | Type | Indhold |
---|---|---|
filepath | string | Fuld sti til fil (inkl. filnavn). |
ANFIL
Denne anmodning er et svar fra klienten til serveren, som transmitterer en fil, som udbedt fra besked RQFIL. Payloaden er de rå binære fildata.
FLFIL
Denne anmodning er et svar fra klienten til serveren, til anmodningen RQFIL, som indikerer at den ikke kan transmittere den ønskede fil. Der er intet payload.
RQPUT
Denne anmodning går fra serveren til klienten og anmoder om at serveren gerne vil sende en fil /eller folder) til klienten. Den næste anmodning er RQFDA som indeholder de binære data. Denne anmodning sender sin payload som JSON.
Hvis der er tale om en folder, så skal stien være afsluttet med / og RQFDA skal ikke sendes.
Felt | Type | Indhold |
---|---|---|
filepath | string | Fuld sti til hvor filen/folderen ønskes gemt (inkl. evt. filnavn). |
mdate | string | Filens datostempel. |
mtime | string | Filens tidsstempel. |
ANPUT
Denne anmodning er et svar fra klienten, der angiver at en fil blev modtaget og gemt uden fejl. Den indeholder intet payload.
FLPUT
Denne anmodning er et svar fra klienten, der angiver at en fil ikke blev modtaget eller der opstod en fejl, da den skulle gemmes. Den indeholder intet payload.
RQFDA
Denne anmodning følger RQPUT og har samme løbenummer som foregående pakke. Den indeholder de rå fildata.
ANFDA
Denne anmodning er et svar fra klienten, der angiver at de rå fildata blev modtaget og gemt uden fejl. Den indeholder intet payload.
FLFDA
Denne anmodning er et svar fra klienten, der angiver at de rå fildate ikke blev modtaget eller der opstod en fejl, da den skulle gemmes. Den indeholder intet payload.
RQDEL
Denne anmodning går fra serveren til klienten og anmoder om at klienten skal slette en given fil/folder.
Felt | Type | Indhold |
---|---|---|
filepath | string | Fuld sti til den fil/folder som skal slettes (inkl. evt. filnavn). |
ANDEL
Denne anmodning er et svar fra klienten, der angiver at en fil blev slettet uden fejl. Den indeholder intet payload.
FLDEL
Denne anmodning er et svar fra klienten, der angiver at en fil ikke kunne slettes. Den indeholder intet payload.
RQMOV
Denne anmodning går fra serveren til klienten og anmoder om at klienten flytter en hel folderstruktur.
Felt | Type | Indhold |
---|---|---|
sourcefilepath | string | Fuldt sti navn for den folder som skal omdøbes/flyttes. |
destinationfilepath | string | Nyt fuldt sti navn for folderen. |
Bemærk at i dette tilfælde, så skal destinationfilepath altid behandles absolut, dvs. den skal ikke omskrives efter reglerne om folder-sammenligning.
Eksempel: sourcefilepath = /todo/a/, indeholder filen /todo/a/x.jpg, destinationfilepath = /todo/b/c/, efter flytning vil filen findes i /todo/b/c/x.jpg.
ANMOV
Denne anmodning er et svar fra klienten, der angiver at en folderstruktur blev flyttet uden fejl. Den indeholder intet payload.
FLMOV
Denne anmodning er et svar fra klienten, der angiver at der opstod en fejl under flytning af folderstrukturen. Den indeholder intet payload. Serveren vil antage at den originale folderstruktur er intakt, dvs. at ingenting blev flyttet.
RQCNV
Denne anmodning er en forespørgsel fra serveren til klienten om at omskrive hele filstrukturen fra en gammel struktur til en ny struktur. Dette gøres ved at alle foldere gennemgås om omdøbes efter følgende principper:
En folder der ender på _39 (underscore og et nummer) omskrives til (39) (mellemrum og nummeret i parentes)
En folder der ender på [39] (nummer i firkantet parentes) omskrives til (39) (samme nummer i almindelige parentes).
Denne anmodning indeholder ingen payload.
ANCNV
Denne anmodning er et svar fra klienten der angiver at konverteringen er gennemført.
FLCNV
Denne anmodning er et svar fra klienten der angiver at konverteringen ikke kunne gennemføres.
RQLOG
Kræver protokol versionsnummer 00002 eller senere.
Denne anmodning går fra serveren til klienten og anmoder om at klienten om at sende log filen for en given dato.
Felt | Type | Indhold |
---|---|---|
logdate | string | Dato i formattet YYYY-MM-DD |
logfile | string | Navnet på den log fil som ønskes, hvis klienten har flere log filer; hvis feltet er tomt så skal klienten sende den vigtigste logfil. Kan osse bruges som filter: klienten skal kunne genkende log filerne newest10 og newest30 og returnerer loggen for de seneste 10 eller 30 minutter. Hver linje i log filen forventes at være afsluttet af “\n” |
ANLOG
Kræver protokol versionsnummer 00002 eller senere.
Denne anmodning er et svar fra klienten som indeholder logfilen. Payload er den rå logfil.
FLLOG
Kræver protokol versionsnummer 00002 eller senere.
Denne anmodning er et svar fra klienten der angiver at logfilen ikke kunne sendes.
RQLST
Kræver protokol versionsnummer 00003 eller senere.
Denne anmodning går fra serveren til klienten, og anmoder om at klienten sender en liste med alle filer og undermapper i en mappe.
Felt | Type | Indhold |
---|---|---|
filepath | string | Navnet på en mappe, skal ende med /. |
ANLST
Kræver protokol versionsnummer 00003 eller senere.
Denne anmodning er et svar fra klient, og indeholder en liste med filer og undermapper.
Felt | Type | Indhold |
---|---|---|
content | array | En liste med de filer og undermapper som findes i mappen. |
Feltet "content" indeholder en liste med filer/undermapper som findes i mappen. Hver fil/undermappe er angivet som et array:
Felt | Type | Indhold |
---|---|---|
filepath | string | Navnet på filen/mappen; hvis navnet ender i / så er det en mappe, ellers er det en fil; dette er hele stien, inkl. f.eks. "/todo/My Task (123)/" |
size | string | Filens størrelse, i bytes (hvis det er en fil) |
mdate | string | Filens ændringsdato |
mtime | string | Filens ændringstidspunkt |
FLLST
Kræver protokol versionsnummer 00003 eller senere.
Denne anmodning er et svar fra klienten der angiver at listen ikke kunne sendes.
Versioner
Versionsnummeret i handshake kan have følgende værdier:
Versionsnummer | Beskrivelse |
---|---|
00001 | Den første version af protokollen |
00002 | Klienten understøtter RQLOG / ANLOG |
00003 | RQCHG understøtter yderligere felter med info om hvor meget der mangler |
Filnavne
Microbizz's fil system tillader ikke følgende tegn i et fil navn eller mappe navn (selvom der sikkert er steder hvor dette ikke overholdes):
/ \ ? < > : " & * |
ASCII værdier under 32 tillades heller ikke. Forbudte tegn fjernes fra fil/mappe navne, så “Ventu A/S” bliver til “Ventu AS”. Se funktionen File::safeName()
.
Flow
Dette er pseudokode, som gennemgår forskellige handlinger.
Konvertering af eksisterende filsynkronisering
resultat = RQCNV IF (resultat == FLCNV) EXIT Vis fejl om at konvertering fejlede Udregn rodfoldere for samtlige objekter baseret på gammel filsynkronisering. Nedlæg gammel filsynkronisering Start ny filsynkronisering med lastchangedate fra gammel filsynkroniserings sidste kørsel.
Opsætning af ny filsynkronisering
Udregn rodfoldere for samtlige objekter Start ny filsynkronisering med lastchangedate 00-00-0000
Filsynkronisering
Der skelnes imellem lastchangedate på MB (lcdMB) og lastchangedate på filserveren (lcdFIL), for at håndtere evt. tidsforskel imellem de to systemer.
newlcdMB = lcdMB Find alle ændrede filer i MB siden lcdMB Forespørg alle ændrede filer på filserveren siden lcdFIL (RQCHG) newlcdFIL = Nyeste dato/tid rapporteret af RQCHG Oversæt denne filliste til lokale rodobjekter vha. principperne for mapper der hedder det samme. operationer = Merge de to ændringslister og skab en liste over operationer der skal udføres. FOR each operationer Udfør operationen ved enten at hente, sende eller slette en fil. Check for forespørgsel af proxyfil og håndter denne. END FOR lcdMB = newlcdMB lcdFIL = newlcdFIL Fortæl filserveren at vi ikke længere er interesserede i ovenstående filer (RQFLS) operationer2 = Hent liste over alle rodobjekter der vil omdøbes. FOR each operationer2 Udfør omdøbningen ved at kalde RQMOV IF (ANMOV) Udskift det eksisterende rodobjekt-foldernavn med det nye foldernavn og fjern det nye navn. ELSE Fjern det nye navn for at fjerne anmodningen (eller lad det ligge for at prøve igen senere) Check for forespørgsel af proxyfil og håndter denne. Husk først at konstruere den fulde sti her, da denne kan have ændret sig siden proxy-filen blev forespurgt. END FOR
Filsynk klient flow
> Klient startes > Indlæser config-fil > Indekser alle nye filer og mapper > Starter file-watcher > Forbinder til MB > Sender Handshake > Venter på kommando fra MB > Svarer på kommando fra MB > (Gå tilbage til "Venter på kommando fra MB)
Registrering af ændringer
node.js klienten benytter sig af et node-modul: node-sentinel-file-watcher (NSFW) som giver giver os mulighed for at lytte på ændringer på system-niveau, system uafhængigt!
Vi har dog været nødvendigt at gøre filewatcher delen som sin egen process, af performance grunde. Vi benytter os a IPC til at kommunikere mellem klient og file-watcher.
FL = file-watcher KL = Klient >FL opdager ændring >FL opsamler info om filen/mappen (modified date/time etc..) >FL sender ændring til KL via IPC >KL Opdager ændring via IPC >KL Tjekker om vi har ændringen i forvejen >(HAR ÆNDRING) KL opdaterer ændringen i ændrings-listen >(HAR IKKE ÆNDRINGEN) KL tilføjer ændringen til ændrings-listen
Grunden til vi opdatere ændringen hvis vi har den, er at en fil kan blive ændret, men slettet eller omdøbt lige efter, så er der ikke nogen grund til at sende for mange ændringer, som bare kan skabe forvirring.
RQCHG
Når vi modtager denne ændring, skal vi sende alle ændringer vi har opdaget efter datoen vi modtog fra Microbizz
MB = Microbizz KL = Klient > MB sender RQCHG kommando med dato/tid: 10-09-2017 12:00 > KL modtager kommando > KL løber hele ændrings-listen igennem for ændringer der opdaget efter det modtaget dato/tid. > KL sender en JSON-liste tilbage med ændringer.
RQFLS
Når vi modtager denne skal vi fjerne alle ændringer som er før den given dato.
MB = Microbizz KL = Klient > MB sender RQFLS kommando med dato/tid: 10-09-2017 12:00 > KL modtager kommando > KL løber hele ændrings-listen igennem for ændringer der opdaget før det modtaget dato/tid. og fjerner dem
RQFIL
Når vi modtager denne kommande skal vi finde filen Microbizz anmoder og sende den tilbage.
MB = Microbizz KL = Klient > MB sender RQFIL kommando med path: /todo/A todo (1)/file.txt > KL modtager kommando > KL forsøger at finde filen først på den direkte path > (Fil findes ikke ved direkte path) KL laver et fuzzy lookup for at se om filen skulle ligge en omdøbt mappe. > KL finder filen og sender den tilbage i en ANFIL kommando > (Fil findes ikke) KL finder ikke filen og sender FLFIL kommando tilbage
RQPUT + RQFDA
Når vi modtager denne kommande skal vi oprette en fil/mappe.
MB = Microbizz KL = Klient !!! HVIS FIL !!! > MB sender RQPUT kommando med path: /todo/A todo (1)/file.txt > KL Modtager kommando > KL tjekker om vi har filen på den direkte path > (KL kan ikke finde fil direkte path) KL laver fuzzy lookup > KL Finder fil > KL gemmer path i et array over filer vi skal til at modtage > KL sender ANPUT tilbage > MB modtager ANPUT fra KL > MB sender RQFDA kommando > KL modtager RQFDA med fil data i payload > KL dobbelt tjekker om vi har har mappen filen skal ligge i. (KL opretter mappen hvis den ikke eksisterer) > KL opretter filen. > KL skriver data til filen som vi modtager det fra MB > KL bliver færdig med at skrive til filen og opdatere timestamps på filen > KL sender ANFDA tilbage til MB !!! HVIS Mappe !!! > MB sender RQPUT kommando med path: /todo/A todo (1)/ > KL Modtager kommando > KL tjekker om vi har mappen på den direkte path > (KL kan ikke finde fil direkte path) KL laver fuzzy lookup > KL Finder ikke mappen > KL opretter mappe med korrekte tidsstempler > KL sender ANPUT tilbage
RQFIL
Her skal vi sende en fil tilbage til MB
MB = Microbizz KL = Klient > MB sender RQFIL til KL > KL Modtager RQFIL > KL forsøger at finde fil > KL finder filen og sender den til MB > KL bliver færdig og sender ANFIL til MB (HVIS KL ikke finder fil) > KL sender FLFIL til MB
RQDEL
Her skal vi slette filen som MB anmoder om.
Dog har vi 3 indstillinger som bestemmer hvad vi skal gøre med den slettet fil:
Flyt den til /trashed/
Ikke gøre noget
Slet permanent
MB = Microbizz KL = Klient > MB sender RQDEL til KL > KL Modtager RQDEL > KL forsøger at finde fil > KL behandler filen afhængig af indstilling af klient. > KL bliver færdig og sender ANDEL til MB (HVIS KL ikke finder fil) > KL sender FLDEL til MB
RQMOV
Når vi modtager denne kommando, skal vi flytte en mappe (Med indhold) til en destination
Vi skal dog være opmærksom på at, vi skal kunne flette mapper sammen, og hvis der er 2 filer med samme navn, skal den nye fil omdøbes, for at sikre vi ikke mister data ved en fejl.
MB = Microbizz KL = Klient > MB sender RQMOV > KL modtager RQMOV > KL tjekker om vi har kilde mappen (Send FLMOV hvis vi ikke har) > KL laver liste over mapper der skal oprettes (Og som filewatcher skal ignorere) > KL tjekker destinationen eksisterer > (Destination eksisterer ikke) KL flytter mappe > (Destination eksisterer) KL forsøger at flette mapperne sammen > KL bliver færdig og sender ANMOV til MB
Incremential RQCHG
When the sync. starts, the server finds all changes since 1970. This can be quite a lot of data, and the server may run out of memory. In protocol version <= 00002 the server would try to find all changes from 1970 to today and send them. In protocol 00003 the server may split the changes in to small periods, so that there are perhaps only 10000 changes that has to be handled at once, so flow may be something like this:
Server sends | Client replies |
---|---|
RQCHG 1970-01-01 | All changes since 1970-0-01 |
RQFIL for the changes from 1970-0-01 to 2004-03-03 | |
RQFLS 2004-03-03 | |
RQCHG 2004-03-04 | All changes since 2004-03-04 |
RQFIL for the changes from 2004-03-04 to 2008-07-21 | |
RQFLS 2008-07-20 | |
RQCHG 2008-07-21 | All changes since 2008-07-21 |
Udvidelse af Filsynken
Pt. har vi nogle flaske halse i filsynken.
F.eks, hvis filsynken er i fuld sving med at synkronisere, kan dette blokere folk i at downloade filer. Derudover blokerer vi også for at MB ikke modtager ændringer imens der er en synkronisering i gang.
Løsningen på dette kunne være at at splitte filsynken op i 3 Websocket processer:
Process #1
Denne process's job er at håndtere de alm. synkroniseringer som MB gerne vil have håndteret. Eksempelvis at der er uploaded nye filer eller oprettet nye mapper i MB som skal overføres til filserveren.
Process #2
Denne process skal udelukkende sende ændringer til MB. Dette kan gøres på 2 måder:
MB spørger selv efter ændringer hvert 30. sek
Filsynk sender ændringerne hver gang, den opdager noget, og derved giver den oplevelse at filerne havner i MB med det samme (Kunne være super effektivt for Proxy brugere)