Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
5.2 kB
1
Indexable
Never
using System;
using System.Collections.Generic;
using System.IO;
using Cysharp.Threading.Tasks;
using RoofStacks.GoArt.Runtime.MonitoringModule.Config;
using RoofStacks.GoArt.Runtime.MonitoringModule.Model;
using RoofStacks.GoArt.Runtime.Services;
using RoofStacks.GoArt.Runtime.WebService;
using RoofStacks.GoArt.Runtime.WebService.Model;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

namespace RoofStacks.GoArt.Runtime.ResourceCachingModule.Service
{
    public sealed class ResourceCachingService : IResourceCachingService
    {
        private readonly ISerializationService _serializationService;
        
        private readonly ILogService _logService;
        
        private readonly IRequester _webRequester;

        private readonly string CACHED_IMAGE_DICTIONARY_FILE_PATH =
            $"{Application.persistentDataPath}/cached_images";

        private Dictionary<string, string> _cachedImageDictionary = new();

        private Queue<string> _cachingQueue = new();

        private bool _isServiceProcessing = false;

        public ResourceCachingService(ISerializationService serializationService, ILogService logService, 
            IRequester webRequester)
        {
            _serializationService = serializationService;
            _logService = logService;
            _webRequester = webRequester;
        }

        public async UniTask<byte[]> GetCachedImageAsync(string imageUrl)
        {
            if (_isServiceProcessing)
            {
                _cachingQueue.Enqueue(imageUrl);
                await UniTask.WaitUntil(() => _isServiceProcessing == false);
            }

            _isServiceProcessing = true;

            try
            {
                _cachedImageDictionary = await _serializationService.DeserializeFromFileAsync<Dictionary<string, string>>(CACHED_IMAGE_DICTIONARY_FILE_PATH);

                if (_cachedImageDictionary == null)
                {
                    await _serializationService.SerializeToFileAsync(_cachedImageDictionary, CACHED_IMAGE_DICTIONARY_FILE_PATH);
                    _cachedImageDictionary = new();
                }

                if (!_cachedImageDictionary.ContainsKey(imageUrl))
                {
                    _cachedImageDictionary.TryAdd(imageUrl, string.Empty);
                }

                _cachedImageDictionary.TryGetValue(imageUrl, out string cachedUrlPath);

                if (string.IsNullOrEmpty(cachedUrlPath))
                {
                    return await DownloadImageFromWebAsync(imageUrl);
                }

                return await GetImageFromCacheAsync(imageUrl);
            }
            finally
            {
                _isServiceProcessing = false;

                if (_cachingQueue.Count > 0)
                {
                    // Process the next image in the queue
                    await GetCachedImageAsync(_cachingQueue.Dequeue());
                }
            }
        }

        private async UniTask<byte[]> DownloadImageFromWebAsync(string imageUrl)
        {
            try
            {
                RequestInfo requestInfo = new RequestInfo(imageUrl);
                RequestResult response = await _webRequester.GetAsync(requestInfo);
                
                if (response.StatusType != StatusType.Success)
                {
                    return default;
                }
                
                byte[] imageData = response.Data;
                string base64ImageData = Convert.ToBase64String(imageData);
                
                if (_cachedImageDictionary.ContainsKey(imageUrl))
                {
                    _cachedImageDictionary[imageUrl] = base64ImageData;
                }
                else
                {
                    _cachedImageDictionary.TryAdd(imageUrl, base64ImageData);
                }

                await _serializationService.SerializeToFileAsync(_cachedImageDictionary, CACHED_IMAGE_DICTIONARY_FILE_PATH);

                return imageData;
            }
            catch (Exception exception)
            {
                _logService.LogError(new Log(LogCode.ResourceCaching.FETCH_IMAGE_ERROR_CODE, exception.Message));
            }

            return Array.Empty<byte>();
        }
        
        private async UniTask<byte[]> GetImageFromCacheAsync(string imageUrl)
        {
            if (!_cachedImageDictionary.ContainsKey(imageUrl))
            { 
                await GetCachedImageAsync(imageUrl);
                return Array.Empty<byte>();
            }
            
            try
            {
                string base64ImageData = _cachedImageDictionary[imageUrl];
                byte[] imageData = Convert.FromBase64String(base64ImageData);
                await _serializationService.SerializeToFileAsync(_cachedImageDictionary, CACHED_IMAGE_DICTIONARY_FILE_PATH);

                return imageData;
            }
            catch (Exception exception)
            {
                _logService.LogError(new Log(LogCode.ResourceCaching.FETCH_IMAGE_ERROR_CODE, exception.Message));
            }
            
            return Array.Empty<byte>();
        }
    }
}


Leave a Comment