Skip to content

Commit

Permalink
Merge pull request #2335 from planetarium/bugfix/table-cache
Browse files Browse the repository at this point in the history
fix table caching
  • Loading branch information
ipdae authored Dec 4, 2023
2 parents 027e866 + 4a896a3 commit 3961dc8
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 7 deletions.
34 changes: 34 additions & 0 deletions NineChronicles.Headless.Tests/GraphTypes/StateQueryTest.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
Expand All @@ -15,6 +16,7 @@
using Nekoyume.Model.Garages;
using Nekoyume.Model.Item;
using Nekoyume.Model.State;
using Nekoyume.TableData;
using NineChronicles.Headless.GraphTypes;
using NineChronicles.Headless.GraphTypes.States;
using NineChronicles.Headless.Tests.Common;
Expand Down Expand Up @@ -222,6 +224,38 @@ public async Task Garage(
}
}

[Theory]
[InlineData(true, "expected")]
[InlineData(false, null)]
public async Task CachedSheet(bool cached, string? expected)
{
var tableName = nameof(ItemRequirementSheet);
var cache = new StateMemoryCache();
var cacheKey = Addresses.GetSheetAddress(tableName).ToString();
if (cached)
{
cache.SheetCache.SetSheet(cacheKey, (Text)expected, TimeSpan.FromMinutes(1));
}
var query = $"{{ cachedSheet(tableName: \"{tableName}\") }}";
MockState mockState = MockState.Empty;
var queryResult = await ExecuteQueryAsync<StateQuery>(
query,
source: new StateContext(
mockState,
0L, cache));
Assert.Null(queryResult.Errors);
var data = (Dictionary<string, object>)((ExecutionNode)queryResult.Data!).ToValue()!;
Assert.Equal(cached, cache.SheetCache.TryGetValue(cacheKey, out _));
if (cached)
{
Assert.Equal(expected, data["cachedSheet"]);
}
else
{
Assert.Null(data["cachedSheet"]);
}
}

private static IEnumerable<object[]> GetMemberDataOfGarages()
{
var agentAddr = new PrivateKey().Address;
Expand Down
39 changes: 39 additions & 0 deletions NineChronicles.Headless.Tests/MemoryCacheExtensionsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Threading.Tasks;
using Bencodex;
using Bencodex.Types;
using MessagePack;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Nekoyume;
using Nekoyume.TableData;
using Xunit;

namespace NineChronicles.Headless.Tests;

public class MemoryCacheExtensionsTest
{
[Fact]
public async Task Sheet()
{
var codec = new Codec();
var lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray);
var cache = new MemoryCache(new OptionsWrapper<MemoryCacheOptions>(new MemoryCacheOptions
{
SizeLimit = null
}));

var sheets = TableSheetsImporter.ImportSheets();
var tableName = nameof(ItemRequirementSheet);
var csv = sheets[tableName];
var cacheKey = Addresses.GetSheetAddress(tableName).ToString();
var value = (Text)csv;
var compressed = MessagePackSerializer.Serialize(codec.Encode(value), lz4Options);
cache.SetSheet(cacheKey, value, TimeSpan.FromMilliseconds(100));
Assert.True(cache.TryGetValue(cacheKey, out byte[] cached));
Assert.Equal(compressed, cached);
Assert.Equal(csv, cache.GetSheet(cacheKey));
await Task.Delay(100);
Assert.False(cache.TryGetValue(cacheKey, out byte[] _));
}
}
2 changes: 1 addition & 1 deletion NineChronicles.Headless/ActionEvaluationPublisher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public ActionEvaluationPublisher(
{
var action = ev.Action;
var sheetAddress = Addresses.GetSheetAddress(action.TableName);
_memoryCache.Set(sheetAddress.ToString(), (Text)action.TableCsv);
_memoryCache.SetSheet(sheetAddress.ToString(), (Text)action.TableCsv, TimeSpan.FromMinutes(1));
}
});
}
Expand Down
7 changes: 2 additions & 5 deletions NineChronicles.Headless/BlockChainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public class BlockChainService : ServiceBase<IBlockChainService>, IBlockChainSer
private ActionEvaluationPublisher _publisher;
private ConcurrentDictionary<string, Sentry.ITransaction> _sentryTraces;
private MemoryCache _memoryCache;
private readonly MessagePackSerializerOptions _lz4Options;

public BlockChainService(
BlockChain blockChain,
Expand All @@ -64,7 +63,6 @@ StateMemoryCache cache
_publisher = actionEvaluationPublisher;
_sentryTraces = sentryTraces;
_memoryCache = cache.SheetCache;
_lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray);
}

public UnaryResult<bool> PutTransaction(byte[] txBytes)
Expand Down Expand Up @@ -245,9 +243,8 @@ public UnaryResult<Dictionary<byte[], byte[]>> GetSheets(
for (int i = 0; i < addresses.Count; i++)
{
var address = addresses[i];
var value = _codec.Encode(values[i] ?? Null.Value);
var compressed = MessagePackSerializer.Serialize(value, _lz4Options);
_memoryCache.Set(address.ToString(), compressed);
var value = values[i] ?? Null.Value;
var compressed = _memoryCache.SetSheet(address.ToString(), value, TimeSpan.FromMinutes(1));
result.TryAdd(address.ToByteArray(), compressed);
}
}
Expand Down
20 changes: 19 additions & 1 deletion NineChronicles.Headless/GraphTypes/StateQuery.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Bencodex;
using Bencodex.Types;
using GraphQL;
using GraphQL.Types;
Expand All @@ -11,7 +12,6 @@
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Arena;
using Nekoyume.Battle;
using Nekoyume.Extensions;
using Nekoyume.Model.Arena;
using Nekoyume.Model.EnumType;
Expand All @@ -32,6 +32,8 @@ namespace NineChronicles.Headless.GraphTypes
{
public partial class StateQuery : ObjectGraphType<StateContext>
{
private readonly Codec _codec = new Codec();

public StateQuery()
{
Name = "StateQuery";
Expand Down Expand Up @@ -699,6 +701,22 @@ public StateQuery()
return result;
}
);

Field<StringGraphType>(
name: "cachedSheet",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<StringGraphType>>
{
Name = "tableName"
}
),
resolve: context =>
{
var tableName = context.GetArgument<string>("tableName");
var cacheKey = Addresses.GetSheetAddress(tableName).ToString();
return context.Source.StateMemoryCache.SheetCache.GetSheet(cacheKey);
}
);
}

public static List<RuneOptionSheet.Row.RuneOptionInfo> GetRuneOptions(
Expand Down
30 changes: 30 additions & 0 deletions NineChronicles.Headless/MemoryCacheExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using Bencodex;
using Bencodex.Types;
using MessagePack;
using Microsoft.Extensions.Caching.Memory;

namespace NineChronicles.Headless;

public static class MemoryCacheExtensions
{
private static readonly Codec Codec = new Codec();
private static readonly MessagePackSerializerOptions Lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray);

public static byte[] SetSheet(this MemoryCache cache, string cacheKey, IValue value, TimeSpan ex)
{
var compressed = MessagePackSerializer.Serialize(Codec.Encode(value), Lz4Options);
cache.Set(cacheKey, compressed, ex);
return compressed;
}

public static string? GetSheet(this MemoryCache cache, string cacheKey)
{
if (cache.TryGetValue(cacheKey, out byte[] cached))
{
return (Text)Codec.Decode(MessagePackSerializer.Deserialize<byte[]>(cached, Lz4Options));
}

return null;
}
}

0 comments on commit 3961dc8

Please sign in to comment.