Skip to content

Commit

Permalink
Onboard azure table storage (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexMacocian authored Nov 25, 2023
1 parent 656d93f commit bd9bcc4
Show file tree
Hide file tree
Showing 19 changed files with 342 additions and 164 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/docker-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ jobs:
run: |
cd GuildWarsPartySearch
$content = Get-Content Config.json
$updatedContent = $content.Replace("[API_KEY_PLACEHOLDER]", "${{ secrets.APIKEY }}")
Set-Content -Path Config.json -Value $updatedContent
$content = $content.Replace("[APIKEY]", "${{ secrets.APIKEY }}")
$content = $content.Replace("[AZURE_TABLESTORAGE_CONNECTIONSTRING]", "${{ secrets.AZURE_TABLESTORAGE_CONNECTIONSTRING }}")
Set-Content -Path Config.json -Value $content
Write-Host "Placeholder replaced successfully in Config.json"
- name: Build and push Docker image
Expand Down
6 changes: 5 additions & 1 deletion GuildWarsPartySearch/Config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"ServerOptions": {
"ApiKey": "[API_KEY_PLACEHOLDER]",
"ApiKey": "[APIKEY]",
"InactivityTimeout": "0:0:5",
"HeartbeatFrequency": "0:0:1"
},
"TableStorageOptions": {
"TableName": "searches",
"ConnectionString": "[AZURE_TABLESTORAGE_CONNECTIONSTRING]"
}
}
40 changes: 27 additions & 13 deletions GuildWarsPartySearch/Endpoints/LiveFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,39 @@ public LiveFeed(
public override void ConnectionClosed()
{
var scopedLogger = this.logger.CreateScopedLogger(nameof(this.ConnectionInitialized), this.ClientData.Socket.RemoteEndPoint?.ToString() ?? string.Empty);
scopedLogger.LogInformation("Client disconnected");
this.liveFeedService.RemoveClient(this.ClientData);
try
{
scopedLogger.LogInformation("Client disconnected");
this.liveFeedService.RemoveClient(this.ClientData);
}
catch(Exception e)
{
scopedLogger.LogError(e, "Encountered exception");
}
}

public override async void ConnectionInitialized()
{
var scopedLogger = this.logger.CreateScopedLogger(nameof(this.ConnectionInitialized), this.ClientData.Socket.RemoteEndPoint?.ToString() ?? string.Empty);
scopedLogger.LogInformation("Client connected");
this.liveFeedService.AddClient(this.ClientData);
scopedLogger.LogInformation("Sending all party searches");
var updates = await this.partySearchService.GetAllPartySearches();
var serialized = JsonConvert.SerializeObject(updates);
var payload = Encoding.UTF8.GetBytes(serialized);
this.SendMessage(new WebsocketMessage
try
{
scopedLogger.LogInformation("Client connected");
this.liveFeedService.AddClient(this.ClientData);
scopedLogger.LogInformation("Sending all party searches");
var updates = await this.partySearchService.GetAllPartySearches(this.ClientData.CancellationToken);
var serialized = JsonConvert.SerializeObject(updates);
var payload = Encoding.UTF8.GetBytes(serialized);
this.SendMessage(new WebsocketMessage
{
Data = payload,
FIN = true,
Opcode = WebsocketMessage.Opcodes.Text
});
}
catch(Exception e)
{
Data = payload,
FIN = true,
Opcode = WebsocketMessage.Opcodes.Text
});
scopedLogger.LogError(e, "Encountered exception");
}
}

public override void HandleReceivedMessage(None message)
Expand Down
78 changes: 47 additions & 31 deletions GuildWarsPartySearch/Endpoints/PostPartySearch.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GuildWarsPartySearch.Server.Models.Endpoints;
using GuildWarsPartySearch.Server.Models;
using GuildWarsPartySearch.Server.Models.Endpoints;
using GuildWarsPartySearch.Server.Services.Feed;
using GuildWarsPartySearch.Server.Services.PartySearch;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -38,38 +39,47 @@ public override void ConnectionInitialized()

public override async void HandleReceivedMessage(PostPartySearchRequest message)
{
var result = await this.partySearchService.PostPartySearch(message);
var response = result.Switch<PostPartySearchResponse>(
onSuccess: _ =>
{
this.liveFeedService.PushUpdate(this.Server, new PartySearchUpdate
var scopedLogger = this.logger.CreateScopedLogger(nameof(this.HandleReceivedMessage), string.Empty);
try
{
var result = await this.partySearchService.PostPartySearch(message, this.ClientData.CancellationToken);
var response = result.Switch<PostPartySearchResponse>(
onSuccess: _ =>
{
Campaign = message.Campaign,
Continent = message.Continent,
District = message.District,
Map = message.Map,
PartySearchEntries = message.PartySearchEntries,
Region = message.Region
this.liveFeedService.PushUpdate(this.Server, new PartySearch
{
Campaign = message.Campaign,
Continent = message.Continent,
District = message.District,
Map = message.Map,
PartySearchEntries = message.PartySearchEntries,
Region = message.Region
});
return Success;
},
onFailure: failure => failure switch
{
PostPartySearchFailure.InvalidPayload => InvalidPayload,
PostPartySearchFailure.InvalidCampaign => InvalidCampaign,
PostPartySearchFailure.InvalidContinent => InvalidContinent,
PostPartySearchFailure.InvalidRegion => InvalidRegion,
PostPartySearchFailure.InvalidMap => InvalidMap,
PostPartySearchFailure.InvalidDistrict => InvalidDistrict,
PostPartySearchFailure.InvalidEntries => InvalidEntries,
PostPartySearchFailure.InvalidPartySize => InvalidPartySize,
PostPartySearchFailure.InvalidPartyMaxSize => InvalidPartyMaxSize,
PostPartySearchFailure.InvalidNpcs => InvalidNpcs,
PostPartySearchFailure.InvalidCharName => InvalidCharName,
PostPartySearchFailure.UnspecifiedFailure => UnspecifiedFailure,
_ => UnspecifiedFailure
});
return Success;
},
onFailure: failure => failure switch
{
PostPartySearchFailure.InvalidPayload => InvalidPayload,
PostPartySearchFailure.InvalidCampaign => InvalidCampaign,
PostPartySearchFailure.InvalidContinent => InvalidContinent,
PostPartySearchFailure.InvalidRegion => InvalidRegion,
PostPartySearchFailure.InvalidMap => InvalidMap,
PostPartySearchFailure.InvalidDistrict => InvalidDistrict,
PostPartySearchFailure.InvalidEntries => InvalidEntries,
PostPartySearchFailure.InvalidPartySize => InvalidPartySize,
PostPartySearchFailure.InvalidPartyMaxSize => InvalidPartyMaxSize,
PostPartySearchFailure.InvalidNpcs => InvalidNpcs,
PostPartySearchFailure.UnspecifiedFailure => UnspecifiedFailure,
_ => UnspecifiedFailure
});

this.SendMessage(response);

this.SendMessage(response);
}
catch(Exception e)
{
scopedLogger.LogError(e, "Encountered exception");
}
}

public override void Tick()
Expand Down Expand Up @@ -142,6 +152,12 @@ public override void Tick()
Description = "Invalid npcs"
};

private static PostPartySearchResponse InvalidCharName => new()
{
Result = 0,
Description = "Invalid char name"
};

private static PostPartySearchResponse UnspecifiedFailure => new()
{
Result = 0,
Expand Down
3 changes: 3 additions & 0 deletions GuildWarsPartySearch/GuildWarsPartySearch.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Data.Tables" Version="12.8.2" />
<PackageReference Include="MTSC" Version="5.5.1" />
<PackageReference Include="Slim" Version="1.9.2" />
<PackageReference Include="Slim.Integration" Version="1.0.4" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="SystemExtensions.NetCore" Version="1.0.1" />
<PackageReference Include="SystemExtensions.NetStandard" Version="1.6.2" />
<PackageReference Include="SystemExtensions.NetStandard.DependencyInjection" Version="1.3.1" />
Expand Down
16 changes: 12 additions & 4 deletions GuildWarsPartySearch/Launch/ServerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using GuildWarsPartySearch.Server.Services.Options;
using GuildWarsPartySearch.Server.Services.PartySearch;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MTSC.Common.Http;
using MTSC.ServerSide;
Expand All @@ -15,7 +16,6 @@
using System.Core.Extensions;
using System.Extensions;
using System.Logging;
using System.Runtime.CompilerServices;
using static MTSC.Common.Http.HttpMessage;

namespace GuildWarsPartySearch.Server.Launch;
Expand All @@ -30,9 +30,17 @@ public static IServiceManager SetupServiceManager(this IServiceManager serviceMa

serviceManager.RegisterResolver(new LoggerResolver());
serviceManager.RegisterOptionsResolver();
serviceManager.RegisterLogWriter<ConsoleLogger>();
serviceManager.RegisterSingleton<ILogsWriter, ConsoleLogger>();
serviceManager.RegisterScoped<ILoggerFactory, ILoggerFactory>(sp =>
{
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddFilter("Azure", LogLevel.Information);
builder.AddProvider(new CVLoggerProvider(sp.GetService<ILogsWriter>()));
});
return loggerFactory;
});
serviceManager.RegisterOptionsManager<JsonOptionsManager>();

return serviceManager;
}

Expand All @@ -41,7 +49,7 @@ public static IServiceCollection SetupServices(this IServiceCollection services)
services.ThrowIfNull();

services.AddScoped<IServerLifetimeService, ServerLifetimeService>();
services.AddScoped<IPartySearchDatabase, InMemoryPartySearchDatabase>();
services.AddScoped<IPartySearchDatabase, TableStorageDatabase>();
services.AddScoped<IPartySearchService, PartySearchService>();
services.AddSingleton<ILiveFeedService, LiveFeedService>();
return services;
Expand Down
10 changes: 0 additions & 10 deletions GuildWarsPartySearch/Models/Database/PartySearch.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public sealed class InvalidNpcs : PostPartySearchFailure
{
}

public sealed class InvalidCharName : PostPartySearchFailure
{
}

public sealed class UnspecifiedFailure : PostPartySearchFailure
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using GuildWarsPartySearch.Common.Models.GuildWars;
using Newtonsoft.Json;

namespace GuildWarsPartySearch.Server.Models.Endpoints;
namespace GuildWarsPartySearch.Server.Models;

public sealed class PartySearchUpdate
public sealed class PartySearch
{
[JsonProperty(nameof(Campaign))]
public Campaign? Campaign { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using Newtonsoft.Json;

namespace GuildWarsPartySearch.Server.Models.Endpoints;
namespace GuildWarsPartySearch.Server.Models;

public sealed class PartySearchEntry
{
[JsonProperty(nameof(CharName))]
public string? CharName { get; set; }

[JsonProperty(nameof(PartySize))]
public int? PartySize { get; set; }

Expand Down
12 changes: 12 additions & 0 deletions GuildWarsPartySearch/Options/TableStorageOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Newtonsoft.Json;

namespace GuildWarsPartySearch.Server.Options;

public sealed class TableStorageOptions
{
[JsonProperty(nameof(TableName))]
public string? TableName { get; set; }

[JsonProperty(nameof(ConnectionString))]
public string? ConnectionString { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using GuildWarsPartySearch.Common.Models.GuildWars;
using GuildWarsPartySearch.Server.Models.Endpoints;
using GuildWarsPartySearch.Server.Models;

namespace GuildWarsPartySearch.Server.Services.Database;

public interface IPartySearchDatabase
{
Task<List<PartySearchUpdate>> GetAllPartySearches();
Task<bool> SetPartySearches(Campaign campaign, Continent continent, Region region, Map map, string district, List<Models.Database.PartySearch> partySearch);
Task<List<Models.Database.PartySearch>?> GetPartySearches(Campaign campaign, Continent continent, Region region, Map map, string district);
Task<List<Server.Models.PartySearch>> GetAllPartySearches(CancellationToken cancellationToken);
Task<bool> SetPartySearches(Campaign campaign, Continent continent, Region region, Map map, string district, List<PartySearchEntry> partySearch, CancellationToken cancellationToken);
Task<List<PartySearchEntry>?> GetPartySearches(Campaign campaign, Continent continent, Region region, Map map, string district, CancellationToken cancellationToken);
}

This file was deleted.

Loading

0 comments on commit bd9bcc4

Please sign in to comment.