Anapher/Strive

View on GitHub
src/Services/ConferenceManagement/Strive.Infrastructure/KeyValue/Repos/PollRepository.cs

Summary

Maintainability
A
0 mins
Test Coverage
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Strive.Core.Services;
using Strive.Core.Services.Poll;
using Strive.Core.Services.Poll.Gateways;
using Strive.Infrastructure.KeyValue.Abstractions;
using Strive.Infrastructure.KeyValue.Extensions;

namespace Strive.Infrastructure.KeyValue.Repos
{
    public class PollRepository : IPollRepository, IKeyValueRepo
    {
        private const string POLLS_PROPERTY_KEY = "polls";
        private const string POLLSTATE_PROPERTY_KEY = "pollState";
        private const string POLLANSWERS_PROPERTY_KEY = "pollAnswers";

        private readonly IKeyValueDatabase _database;

        public PollRepository(IKeyValueDatabase database)
        {
            _database = database;
        }

        public async ValueTask CreatePoll(string conferenceId, Poll poll)
        {
            var pollsKey = GetPollsKey(conferenceId);
            await _database.HashSetAsync(pollsKey, poll.Id, poll);
        }

        public async ValueTask DeletePollAndState(string conferenceId, string pollId)
        {
            var pollsKey = GetPollsKey(conferenceId);
            var stateKey = GetPollStateKey(conferenceId);

            using var transaction = _database.CreateTransaction();
            _ = transaction.HashDeleteAsync(pollsKey, pollId);
            _ = transaction.HashDeleteAsync(stateKey, pollId);

            await transaction.ExecuteAsync();
        }

        public async ValueTask<IReadOnlyDictionary<string, PollAnswerWithKey>> DeletePollAnswers(string conferenceId,
            string pollId)
        {
            var key = GetPollAnswersKey(conferenceId, pollId);

            using var transaction = _database.CreateTransaction();
            var answersTask = _database.HashGetAllAsync<PollAnswerWithKey>(key);
            _ = transaction.KeyDeleteAsync(key);

            await transaction.ExecuteAsync();

            return (await answersTask)!;
        }

        public async ValueTask<PollState?> SetPollState(string conferenceId, string pollId, PollState state)
        {
            var stateKey = GetPollStateKey(conferenceId);

            using var transaction = _database.CreateTransaction();
            var previousPollTask = transaction.HashGetAsync<PollState>(stateKey, pollId);
            _ = transaction.HashSetAsync(stateKey, pollId, state);

            await transaction.ExecuteAsync();

            return await previousPollTask;
        }

        public async ValueTask<IReadOnlyList<Poll>> GetPollsOfConference(string conferenceId)
        {
            var pollsKey = GetPollsKey(conferenceId);
            var result = await _database.HashGetAllAsync<Poll>(pollsKey);
            return result.Values.ToList()!;
        }

        public async ValueTask<Poll?> GetPoll(string conferenceId, string pollId)
        {
            var pollsKey = GetPollsKey(conferenceId);
            return await _database.HashGetAsync<Poll>(pollsKey, pollId);
        }

        public async ValueTask<PollState?> GetPollState(string conferenceId, string pollId)
        {
            var stateKey = GetPollStateKey(conferenceId);
            return await _database.HashGetAsync<PollState>(stateKey, pollId);
        }

        public async ValueTask<IReadOnlyDictionary<string, PollState>> GetStateOfAllPolls(string conferenceId)
        {
            var stateKey = GetPollStateKey(conferenceId);
            return (await _database.HashGetAllAsync<PollState>(stateKey))!;
        }

        public async ValueTask SetPollAnswer(Participant participant, string pollId, PollAnswerWithKey answer)
        {
            var key = GetPollAnswersKey(participant.ConferenceId, pollId);
            await _database.HashSetAsync(key, participant.Id, answer);
        }

        public async ValueTask DeletePollAnswer(Participant participant, string pollId)
        {
            var key = GetPollAnswersKey(participant.ConferenceId, pollId);
            await _database.HashDeleteAsync(key, participant.Id);
        }

        public async ValueTask<IReadOnlyDictionary<string, PollAnswerWithKey>> GetPollAnswersOfParticipant(
            Participant participant, IEnumerable<string> pollIds)
        {
            using var transaction = _database.CreateTransaction();

            var values = pollIds.ToDictionary(pollId => pollId,
                pollId => transaction.HashGetAsync<PollAnswerWithKey>(
                    GetPollAnswersKey(participant.ConferenceId, pollId), participant.Id));

            await transaction.ExecuteAsync();

            var result = new Dictionary<string, PollAnswerWithKey>();
            foreach (var (pollId, valueTask) in values)
            {
                var answer = await valueTask;
                if (answer == null) continue;

                result.Add(pollId, answer);
            }

            return result;
        }

        public async ValueTask<IReadOnlyDictionary<string, PollAnswerWithKey>> GetPollAnswers(string conferenceId,
            string pollId)
        {
            var key = GetPollAnswersKey(conferenceId, pollId);
            return (await _database.HashGetAllAsync<PollAnswerWithKey>(key))!;
        }

        public async ValueTask<PollAnswerWithKey?> GetPollAnswer(Participant participant, string pollId)
        {
            var key = GetPollAnswersKey(participant.ConferenceId, pollId);
            return await _database.HashGetAsync<PollAnswerWithKey>(key, participant.Id);
        }

        private static string GetPollsKey(string conferenceId)
        {
            return DatabaseKeyBuilder.ForProperty(POLLS_PROPERTY_KEY).ForConference(conferenceId).ToString();
        }

        private static string GetPollStateKey(string conferenceId)
        {
            return DatabaseKeyBuilder.ForProperty(POLLSTATE_PROPERTY_KEY).ForConference(conferenceId).ToString();
        }

        private static string GetPollAnswersKey(string conferenceId, string pollId)
        {
            return DatabaseKeyBuilder.ForProperty(POLLANSWERS_PROPERTY_KEY).ForConference(conferenceId)
                .ForSecondary(pollId).ToString();
        }
    }
}