/// <summary> /// Host app must call this when receiving http request on POST /api/retro/main /// </summary> public async Task <MainResponse> HandleHttpMain(MainRequest req) { var resp = new MainResponse(); try { var user = ClientPlex.GetUser(req.SessionKey); if (user == null) { return new MainResponse { ErrorCode = Constants.ERRCODE_BADUSER } } ; await HandleHttpMain(req, user, resp); } catch (Exception ex) { resp.ErrorCode = Constants.ERRCODE_INTERNAL; Diagnostics.ReportClientCallError?.Invoke(ex.ToString()); } return(resp); }
private async Task HandleHttpMain(MainRequest req, IUser user, MainResponse resp) { //initialize if (req.Initialze != null) { resp.DataDictionary = Retrovert.DataDictionaryToWire(DataDictionary, user, LanguageMessages); } //load datons if (req.GetDatons != null) { var getResponses = new List <GetDatonResponse>(); foreach (var drequest in req.GetDatons) { var loadResult = await GetDaton(DatonKey.Parse(drequest.Key), user, forceCheckLatest : drequest.ForceLoad); var getResponse = new GetDatonResponse { Errors = loadResult.Errors }; if (loadResult.Daton != null) //null means it was not found by key, usually { bool doReturnToCaller = loadResult.Daton.Version == null || drequest.KnownVersion != loadResult.Daton.Version; //omit if client already has the current version if (doReturnToCaller) { getResponse.CondensedDaton = new CondensedDatonResponse { CondensedDatonJson = Retrovert.ToWire(DataDictionary, loadResult.Daton, false) }; } if (drequest.DoSubscribe && loadResult.Daton is Persiston) { ClientPlex.ManageSubscribe(req.SessionKey, loadResult.Daton.Key, loadResult.Daton.Version, true); } } else { getResponse.Key = drequest.Key; //only needed if daton is not returned to client } getResponses.Add(getResponse); } resp.GetDatons = getResponses.ToArray(); } //save datons if (req.SaveDatons != null) { var diffs = new List <PersistonDiff>(); foreach (var saveRequest in req.SaveDatons) { var diff = Retrovert.FromDiff(DataDictionary, saveRequest); diffs.Add(diff); } (bool success, var results) = await SaveDatons(req.SessionKey, user, diffs.ToArray()); var saveResponses = new List <SavePersistonResponse>(); foreach (var result in results) { saveResponses.Add(new SavePersistonResponse { IsDeleted = result.IsDeleted, IsSuccess = result.IsSuccess, OldKey = result.OldKey.ToString(), NewKey = result.NewKey?.ToString(), Errors = result.Errors }); } resp.SavedPersistons = saveResponses.ToArray(); resp.SavePersistonsSuccess = success; } //change datons state if (req.ManageDatons != null) { var manageResponses = new List <ManageDatonResponse>(req.ManageDatons.Length); foreach (var mrequest in req.ManageDatons) { //what does the caller wants to change? var datonKey = DatonKey.Parse(mrequest.Key); bool wantsLock = mrequest.SubscribeState == 2; bool wantsSubscribe = mrequest.SubscribeState >= 1; //handle change in subscription //(Performance note: unsubscribe should happen before unlock so that the unlock-propogation can short circuit reloading. Ultimately //if only one client is dealing with a daton and that client releases the lock and subscription, this server can forget about it //immediately.) bool isSubscribed = false; if (datonKey is PersistonKey) { ClientPlex.ManageSubscribe(req.SessionKey, datonKey, mrequest.Version, wantsSubscribe); isSubscribed = wantsSubscribe; } //handle change in lock string lockErrorCode = ""; bool hasLock = false; if (wantsLock) { if (string.IsNullOrEmpty(mrequest.Version)) { throw new Exception("Version required to lock daton"); } (hasLock, lockErrorCode) = LockManager.RequestLock(datonKey, mrequest.Version, req.SessionKey); } else { LockManager.ReleaseLock(datonKey, req.SessionKey); } manageResponses.Add(new ManageDatonResponse { ErrorCode = lockErrorCode, Key = mrequest.Key, SubscribeState = hasLock ? 2 : (isSubscribed ? 1 : 0) }); } resp.ManageDatons = manageResponses.ToArray(); } //quit - free up locks and memory if (req.DoQuit) { ClientPlex.DeleteSession(req.SessionKey); LockManager.ReleaseLocksForSession(req.SessionKey); } }