potentially fixes an issue with cache creation, do not remove mediator on failure
This commit is contained in:
2
MareAPI
2
MareAPI
Submodule MareAPI updated: 381f9a4808...85bedb49e3
@@ -25,7 +25,6 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
private readonly TransientResourceManager _transientResourceManager;
|
||||
private readonly FileCacheManager _fileCacheManager;
|
||||
private readonly PerformanceCollector _performanceCollector;
|
||||
private readonly ConcurrentQueue<Task<string>> _processingQueue = new();
|
||||
|
||||
public CharacterDataFactory(ILogger<CharacterDataFactory> logger, DalamudUtil dalamudUtil, IpcManager ipcManager,
|
||||
TransientResourceManager transientResourceManager, FileCacheManager fileReplacementFactory, MareMediator mediator,
|
||||
@@ -37,13 +36,6 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
_transientResourceManager = transientResourceManager;
|
||||
_fileCacheManager = fileReplacementFactory;
|
||||
_performanceCollector = performanceCollector;
|
||||
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) =>
|
||||
{
|
||||
while (_processingQueue.TryDequeue(out var result))
|
||||
{
|
||||
result.RunSynchronously();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private unsafe bool CheckForNullDrawObject(IntPtr playerPointer)
|
||||
@@ -51,14 +43,14 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
return ((Character*)playerPointer)->GameObject.DrawObject == null;
|
||||
}
|
||||
|
||||
public async Task<CharacterData> BuildCharacterData(CharacterData previousData, GameObjectHandler playerRelatedObject, CancellationToken token)
|
||||
public async Task BuildCharacterData(CharacterData previousData, GameObjectHandler playerRelatedObject, CancellationToken token)
|
||||
{
|
||||
if (!_ipcManager.Initialized)
|
||||
{
|
||||
throw new InvalidOperationException("Penumbra is not connected");
|
||||
}
|
||||
|
||||
if (playerRelatedObject == null) return previousData;
|
||||
if (playerRelatedObject == null) return;
|
||||
|
||||
bool pointerIsZero = true;
|
||||
try
|
||||
@@ -84,7 +76,7 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
_logger.LogTrace("Pointer was zero for {objectKind}", playerRelatedObject.ObjectKind);
|
||||
previousData.FileReplacements.Remove(playerRelatedObject.ObjectKind);
|
||||
previousData.GlamourerString.Remove(playerRelatedObject.ObjectKind);
|
||||
return previousData;
|
||||
return;
|
||||
}
|
||||
|
||||
var previousFileReplacements = previousData.FileReplacements.ToDictionary(d => d.Key, d => d.Value);
|
||||
@@ -92,15 +84,14 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
|
||||
try
|
||||
{
|
||||
_processingQueue.Clear();
|
||||
return await _performanceCollector.LogPerformance(this, "CreateCharacterData>" + playerRelatedObject.ObjectKind, async () =>
|
||||
await _performanceCollector.LogPerformance(this, "CreateCharacterData>" + playerRelatedObject.ObjectKind, async () =>
|
||||
{
|
||||
return await CreateCharacterData(previousData, playerRelatedObject, token).ConfigureAwait(false);
|
||||
await CreateCharacterData(previousData, playerRelatedObject, token).ConfigureAwait(false);
|
||||
}).ConfigureAwait(true);
|
||||
return;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_processingQueue.Clear();
|
||||
_logger.LogDebug("Cancelled creating Character data for {object}", playerRelatedObject);
|
||||
throw;
|
||||
}
|
||||
@@ -111,7 +102,7 @@ public class CharacterDataFactory : MediatorSubscriberBase
|
||||
|
||||
previousData.FileReplacements = previousFileReplacements;
|
||||
previousData.GlamourerString = previousGlamourerData;
|
||||
return previousData;
|
||||
return;
|
||||
}
|
||||
|
||||
private async Task<CharacterData> CreateCharacterData(CharacterData previousData, GameObjectHandler playerRelatedObject, CancellationToken token)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
using MareSynchronos.Factories;
|
||||
using MareSynchronos.Mediator;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Collections;
|
||||
|
||||
namespace MareSynchronos.Managers;
|
||||
|
||||
@@ -14,7 +12,7 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
private readonly CharacterDataFactory _characterDataFactory;
|
||||
private Task? _cacheCreationTask;
|
||||
private readonly Dictionary<ObjectKind, GameObjectHandler> _cachesToCreate = new();
|
||||
private readonly CharacterData _lastCreatedData = new();
|
||||
private readonly CharacterData _playerData = new();
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
private readonly List<GameObjectHandler> _playerRelatedObjects = new();
|
||||
private CancellationTokenSource _palettePlusCts = new();
|
||||
@@ -43,9 +41,9 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
Task.Run(() =>
|
||||
{
|
||||
var actualMsg = (ClearCacheForObjectMessage)msg;
|
||||
_lastCreatedData.FileReplacements.Remove(actualMsg.ObjectToCreateFor.ObjectKind);
|
||||
_lastCreatedData.GlamourerString.Remove(actualMsg.ObjectToCreateFor.ObjectKind);
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData));
|
||||
_playerData.FileReplacements.Remove(actualMsg.ObjectToCreateFor.ObjectKind);
|
||||
_playerData.GlamourerString.Remove(actualMsg.ObjectToCreateFor.ObjectKind);
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||
});
|
||||
});
|
||||
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (msg) => ProcessCacheCreation());
|
||||
@@ -57,9 +55,9 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
|
||||
private void PalettePlusChanged(PalettePlusMessage msg)
|
||||
{
|
||||
if (!string.Equals(msg.Data, _lastCreatedData.PalettePlusPalette, StringComparison.Ordinal))
|
||||
if (!string.Equals(msg.Data, _playerData.PalettePlusPalette, StringComparison.Ordinal))
|
||||
{
|
||||
_lastCreatedData.PalettePlusPalette = msg.Data ?? string.Empty;
|
||||
_playerData.PalettePlusPalette = msg.Data ?? string.Empty;
|
||||
|
||||
_palettePlusCts?.Cancel();
|
||||
_palettePlusCts?.Dispose();
|
||||
@@ -69,26 +67,26 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), token).ConfigureAwait(false);
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData));
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||
}, token);
|
||||
}
|
||||
}
|
||||
|
||||
private void HeelsOffsetChanged(HeelsOffsetMessage msg)
|
||||
{
|
||||
if (msg.Offset != _lastCreatedData.HeelsOffset)
|
||||
if (msg.Offset != _playerData.HeelsOffset)
|
||||
{
|
||||
_lastCreatedData.HeelsOffset = msg.Offset;
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData));
|
||||
_playerData.HeelsOffset = msg.Offset;
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||
}
|
||||
}
|
||||
|
||||
private void CustomizePlusChanged(CustomizePlusMessage msg)
|
||||
{
|
||||
if (!string.Equals(msg.Data, _lastCreatedData.CustomizePlusScale, StringComparison.Ordinal))
|
||||
if (!string.Equals(msg.Data, _playerData.CustomizePlusScale, StringComparison.Ordinal))
|
||||
{
|
||||
_lastCreatedData.CustomizePlusScale = msg.Data ?? string.Empty;
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData));
|
||||
_playerData.CustomizePlusScale = msg.Data ?? string.Empty;
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +102,18 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
{
|
||||
foreach (var obj in toCreate)
|
||||
{
|
||||
var data = await _characterDataFactory.BuildCharacterData(_lastCreatedData, obj.Value, _cts.Token).ConfigureAwait(false);
|
||||
await _characterDataFactory.BuildCharacterData(_playerData, obj.Value, _cts.Token).ConfigureAwait(false);
|
||||
}
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_lastCreatedData));
|
||||
|
||||
int maxWaitingTime = 10000;
|
||||
while (!_playerData.IsReady && maxWaitingTime > 0)
|
||||
{
|
||||
await Task.Delay(100).ConfigureAwait(false);
|
||||
maxWaitingTime -= 100;
|
||||
_logger.LogTrace("Waiting for Cache to be ready");
|
||||
}
|
||||
|
||||
Mediator.Publish(new CharacterDataCreatedMessage(_playerData.ToAPI()));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -115,7 +122,6 @@ public class CacheCreationService : MediatorSubscriberBase, IDisposable
|
||||
finally
|
||||
{
|
||||
_logger.LogDebug("Cache Creation complete");
|
||||
|
||||
}
|
||||
}, _cts.Token);
|
||||
}
|
||||
|
||||
@@ -378,6 +378,7 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
|
||||
if (downloadToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogTrace("Detected cancellation");
|
||||
_apiController.CancelDownload(downloadId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -415,12 +416,6 @@ public class CachedPlayer : MediatorSubscriberBase, IDisposable
|
||||
|
||||
_logger.LogDebug("[{applicationId}] Application finished", _applicationId);
|
||||
});
|
||||
|
||||
_downloadCancellationTokenSource = null;
|
||||
|
||||
_logger.LogDebug("Download was cancelled");
|
||||
_apiController.CancelDownload(downloadId);
|
||||
|
||||
}, downloadToken);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class OnlinePlayerManager : MediatorSubscriberBase, IDisposable
|
||||
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => FrameworkOnUpdate());
|
||||
Mediator.Subscribe<CharacterDataCreatedMessage>(this, (msg) =>
|
||||
{
|
||||
var newData = ((CharacterDataCreatedMessage)msg).CharacterData.ToAPI();
|
||||
var newData = ((CharacterDataCreatedMessage)msg).CharacterData;
|
||||
if (_lastSentData == null || _lastSentData != null && !string.Equals(newData.DataHash.Value, _lastSentData.DataHash.Value, StringComparison.Ordinal))
|
||||
{
|
||||
_logger.LogDebug("Pushing data for visible players");
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<Authors></Authors>
|
||||
<Company></Company>
|
||||
<Version>0.7.39</Version>
|
||||
<Version>0.7.40</Version>
|
||||
<Description></Description>
|
||||
<Copyright></Copyright>
|
||||
<PackageProjectUrl>https://github.com/Penumbra-Sync/client</PackageProjectUrl>
|
||||
|
||||
@@ -22,6 +22,7 @@ public class MareMediator : IDisposable
|
||||
private readonly ILogger<MareMediator> _logger;
|
||||
private readonly PerformanceCollector _performanceCollector;
|
||||
private readonly object _addRemoveLock = new();
|
||||
private readonly Dictionary<object, DateTime> _lastErrorTime = new();
|
||||
|
||||
public MareMediator(ILogger<MareMediator> logger, PerformanceCollector performanceCollector)
|
||||
{
|
||||
@@ -69,11 +70,13 @@ public class MareMediator : IDisposable
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lock (_addRemoveLock)
|
||||
if (_lastErrorTime.TryGetValue(subscriber, out var lastErrorTime))
|
||||
{
|
||||
var removed = _subscriberDict[message.GetType()].RemoveWhere(s => s == subscriber);
|
||||
_logger.LogCritical(ex, "Error executing {type} for subscriber {subscriber}, removed from Mediator: {removeCount}", message.GetType().Name, subscriber.Subscriber.GetType().Name, removed);
|
||||
if (lastErrorTime.Add(TimeSpan.FromSeconds(10)) > DateTime.UtcNow) continue;
|
||||
}
|
||||
|
||||
_logger.LogCritical(ex, "Error executing {type} for subscriber {subscriber}", message.GetType().Name, subscriber.Subscriber.GetType().Name);
|
||||
_lastErrorTime[subscriber] = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ public record NotificationMessage
|
||||
(string Title, string Message, NotificationType Type, uint TimeShownOnScreen = 3000) : IMessage;
|
||||
public record CreateCacheForObjectMessage(GameObjectHandler ObjectToCreateFor) : IMessage;
|
||||
public record ClearCacheForObjectMessage(GameObjectHandler ObjectToCreateFor) : IMessage;
|
||||
public record CharacterDataCreatedMessage(CharacterData CharacterData) : IMessage;
|
||||
public record CharacterDataCreatedMessage(API.Data.CharacterData CharacterData) : IMessage;
|
||||
public record PenumbraStartRedrawMessage(IntPtr Address) : IMessage;
|
||||
public record PenumbraEndRedrawMessage(IntPtr Address) : IMessage;
|
||||
public record HubReconnectingMessage(Exception? Exception) : IMessage;
|
||||
|
||||
@@ -1,31 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Text;
|
||||
using System.Text;
|
||||
using MareSynchronos.API.Data.Enum;
|
||||
using MareSynchronos.API.Data;
|
||||
|
||||
namespace MareSynchronos.Models;
|
||||
|
||||
[JsonObject(MemberSerialization.OptIn)]
|
||||
public class CharacterData
|
||||
{
|
||||
[JsonProperty]
|
||||
public Dictionary<ObjectKind, HashSet<FileReplacement>> FileReplacements { get; set; } = new();
|
||||
|
||||
[JsonProperty]
|
||||
public Dictionary<ObjectKind, string> GlamourerString { get; set; } = new();
|
||||
|
||||
public bool IsReady => FileReplacements.SelectMany(k => k.Value).All(f => f.Computed);
|
||||
|
||||
[JsonProperty]
|
||||
public string ManipulationString { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty]
|
||||
public float HeelsOffset { get; set; } = 0f;
|
||||
|
||||
[JsonProperty]
|
||||
public string CustomizePlusScale { get; set; } = string.Empty;
|
||||
|
||||
[JsonProperty]
|
||||
public string PalettePlusPalette { get; set; } = string.Empty;
|
||||
|
||||
public API.Data.CharacterData ToAPI()
|
||||
|
||||
@@ -62,7 +62,7 @@ public class SettingsUi : WindowMediatorSubscriberBase, IDisposable
|
||||
Mediator.Subscribe<SwitchToIntroUiMessage>(this, (_) => IsOpen = false);
|
||||
Mediator.Subscribe<CutsceneStartMessage>(this, (_) => UiShared_GposeStart());
|
||||
Mediator.Subscribe<CutsceneEndMessage>(this, (_) => UiShared_GposeEnd());
|
||||
Mediator.Subscribe<CharacterDataCreatedMessage>(this, (msg) => LastCreatedCharacterData = ((CharacterDataCreatedMessage)msg).CharacterData.ToAPI());
|
||||
Mediator.Subscribe<CharacterDataCreatedMessage>(this, (msg) => LastCreatedCharacterData = ((CharacterDataCreatedMessage)msg).CharacterData);
|
||||
|
||||
windowSystem.AddWindow(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user