Example #1
0
        public async Task SaveSurveyResponseAsync([FromBody] ClientModels.SurveyAnswer surveyAnswer)
        {
            if (surveyAnswer == null)
            {
                throw new ArgumentNullException(nameof(surveyAnswer));
            }

            if (ModelState.IsValid)
            {
                try
                {
                    var queue = await _stateManager.GetOrAddAsync <IReliableConcurrentQueue <ClientModels.SurveyAnswer> >("surveyQueue");

                    if (surveyAnswer.Id == null)
                    {
                        surveyAnswer.Id = Guid.NewGuid().ToString();
                    }

                    using (var tx = _stateManager.CreateTransaction())
                    {
                        await queue.EnqueueAsync(tx, surveyAnswer);

                        await tx.CommitAsync();
                    }
                }
                catch (Exception ex)
                {
                    ServiceEventSource.Current.ServiceRequestFailed(ex.ToString());
                    throw;
                }
            }
        }
Example #2
0
        public async Task MergeSurveyAnswerToAnalysisAsync([FromBody] ClientModels.SurveyAnswer surveyAnswer)
        {
            try
            {
                var surveyAnswersSummaryCache = Connection.GetDatabase();
                var success = false;

                do
                {
                    var result = await surveyAnswersSummaryCache.StringGetAsync(surveyAnswer.SlugName);

                    var isNew       = result.IsNullOrEmpty;
                    var transaction = surveyAnswersSummaryCache.CreateTransaction();

                    SurveyAnswersSummary surveyAnswersSummary = null;

                    if (isNew)
                    {
                        transaction.AddCondition(Condition.KeyNotExists(surveyAnswer.SlugName));
                        surveyAnswersSummary = new SurveyAnswersSummary(surveyAnswer.SlugName);
                    }
                    else
                    {
                        surveyAnswersSummary = JsonConvert.DeserializeObject <SurveyAnswersSummary>(result);
                        transaction.AddCondition(Condition.StringEqual(surveyAnswer.SlugName, result));
                    }

                    ServiceEventSource.Current.Message("Slug name:{0}|Total answers:{1}", surveyAnswersSummary.SlugName,
                                                       surveyAnswersSummary.TotalAnswers);

                    // Add and merge the new answer to new or existing summary
                    surveyAnswersSummary.AddNewAnswer(surveyAnswer.ToSurveyAnswer());

                    transaction.StringSetAsync(surveyAnswer.SlugName,
                                               JsonConvert.SerializeObject(surveyAnswersSummary));

                    //This is a simple implementation of optimistic concurrency.
                    //If transaction fails, another user must have edited the same survey.
                    //If so, try to process this survey answer again.

                    //Another approach is to store each survey answer option as a separate hash in Redis and simply increment
                    //the hash value. This technique will not cause collisions with other threads but will require a redesign of
                    //how survey answer summaries are stored in redis. This approach is left to the reader to implement.

                    success = await transaction.ExecuteAsync();
                } while (!success);
            }
            catch (Exception ex)
            {
                ServiceEventSource.Current.ServiceRequestFailed(ex.ToString());
                throw;
            }
        }
Example #3
0
        public static ApiModels.SurveyAnswer ToSurveyAnswer(this ClientModels.SurveyAnswer surveyAnswer)
        {
            if (surveyAnswer == null)
            {
                throw new ArgumentNullException(nameof(surveyAnswer));
            }

            return(new ApiModels.SurveyAnswer()
            {
                CreatedOn = surveyAnswer.CreatedOn,
                QuestionAnswers = surveyAnswer.QuestionAnswers.Select(qa => qa.ToQuestionAnswer()).ToList(),
                SlugName = surveyAnswer.SlugName,
                Title = surveyAnswer.Title
            });
        }