6 "github.com/iotbzh/xds-agent/lib/apiv1"
7 st "github.com/iotbzh/xds-agent/lib/syncthing"
10 // IPROJECT interface implementation for syncthing projects
13 type STProject struct {
16 folder *XdsFolderConfig
20 // NewProjectST Create a new instance of STProject
21 func NewProjectST(ctx *Context, svr *XdsServer) *STProject {
25 folder: &XdsFolderConfig{},
31 func (p *STProject) Add(cfg apiv1.ProjectConfig) (*apiv1.ProjectConfig, error) {
34 // Add project/folder into XDS Server
35 err = p.server.FolderAdd(p.server.ProjectToFolder(cfg), p.folder)
39 svrPrj := p.GetProject()
41 // Declare project into local Syncthing
42 id, err := p.SThg.FolderChange(st.FolderChangeArg{
45 RelativePath: cfg.ClientPath,
46 SyncThingID: p.server.ServerConfig.Builder.SyncThingID,
52 locPrj, err := p.SThg.FolderConfigGet(id)
54 svrPrj.Status = apiv1.StatusErrorConfig
57 if svrPrj.ID != locPrj.ID {
58 p.Log.Errorf("Project ID in XDSServer and local ST differ: %s != %s", svrPrj.ID, locPrj.ID)
61 // Use Setup function to setup remains fields
62 return p.Setup(*svrPrj)
66 func (p *STProject) Delete() error {
67 errSvr := p.server.FolderDelete(p.folder.ID)
68 errLoc := p.SThg.FolderDelete(p.folder.ID)
75 // GetProject Get public part of project config
76 func (p *STProject) GetProject() *apiv1.ProjectConfig {
77 prj := p.server.FolderToProject(*p.folder)
78 prj.ServerID = p.server.ID
82 // Setup Setup local project config
83 func (p *STProject) Setup(prj apiv1.ProjectConfig) (*apiv1.ProjectConfig, error) {
85 p.folder = p.server.ProjectToFolder(prj)
86 svrPrj := p.GetProject()
88 // Register events to update folder status
89 // Register to XDS Server events
90 p.server.EventOn("event:folder-state-change", "", p._cbServerFolderChanged)
91 if err := p.server.EventRegister("folder-state-change", svrPrj.ID); err != nil {
92 p.Log.Warningf("XDS Server EventRegister failed: %v", err)
96 // Register to Local Syncthing events
97 for _, evName := range []string{st.EventStateChanged, st.EventFolderPaused} {
98 evID, err := p.SThg.Events.Register(evName, p._cbLocalSTEvents, svrPrj.ID, nil)
102 p.eventIDs = append(p.eventIDs, evID)
108 // Update Update some field of a project
109 func (p *STProject) Update(prj apiv1.ProjectConfig) (*apiv1.ProjectConfig, error) {
111 if p.folder.ID != prj.ID {
112 return nil, fmt.Errorf("Invalid id")
115 err := p.server.FolderUpdate(p.server.ProjectToFolder(prj), p.folder)
120 return p.GetProject(), nil
123 // GetServer Get the XdsServer that holds this project
124 func (p *STProject) GetServer() *XdsServer {
128 // Sync Force project files synchronization
129 func (p *STProject) Sync() error {
130 if err := p.server.FolderSync(p.folder.ID); err != nil {
133 return p.SThg.FolderScan(p.folder.ID, "")
136 // IsInSync Check if project files are in-sync
137 func (p *STProject) IsInSync() (bool, error) {
138 // Should be up-to-date by callbacks (see below)
139 return p.folder.IsInSync, nil
146 // callback use to update (XDS Server) folder IsInSync status
148 func (p *STProject) _cbServerFolderChanged(pData interface{}, data interface{}) error {
149 evt := data.(XdsEventFolderChange)
151 // Only process event that concerns this project/folder ID
152 if p.folder.ID != evt.Folder.ID {
156 if evt.Folder.IsInSync != p.folder.DataCloudSync.STSvrIsInSync ||
157 evt.Folder.Status != p.folder.DataCloudSync.STSvrStatus {
159 p.folder.DataCloudSync.STSvrIsInSync = evt.Folder.IsInSync
160 p.folder.DataCloudSync.STSvrStatus = evt.Folder.Status
162 if err := p.events.Emit(apiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
163 p.Log.Warningf("Cannot notify project change (from server): %v", err)
169 // callback use to update IsInSync status
170 func (p *STProject) _cbLocalSTEvents(ev st.Event, data *st.EventsCBData) {
172 inSync := p.folder.DataCloudSync.STLocIsInSync
173 sts := p.folder.DataCloudSync.STLocStatus
179 case st.EventStateChanged:
182 case "scanning", "syncing":
183 sts = apiv1.StatusSyncing
185 sts = apiv1.StatusEnable
187 inSync = (to == "idle")
189 case st.EventFolderPaused:
190 if sts == apiv1.StatusEnable {
191 sts = apiv1.StatusPause
196 if prevSync != inSync || prevStatus != sts {
198 p.folder.DataCloudSync.STLocIsInSync = inSync
199 p.folder.DataCloudSync.STLocStatus = sts
201 if err := p.events.Emit(apiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
202 p.Log.Warningf("Cannot notify project change (local): %v", err)