Skip to content

Commit

Permalink
Merge pull request #1845 from tgstation/FixInstanceDelete
Browse files Browse the repository at this point in the history
Fix Instance Detach Database Conflicts
  • Loading branch information
Cyberboss authored Aug 4, 2024
2 parents 0ce9235 + f1eaf9b commit e958a50
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 21 deletions.
60 changes: 59 additions & 1 deletion .github/workflows/ci-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,64 @@ jobs:
cd tests/DMAPI/BasicOperation
$HOME/OpenDream/tgs_deploy/bin/compiler/DMCompiler --verbose --notices-enabled "basic operation_test.dme"
efcore-version-match:
name: Check Nuget Versions Match Tools
runs-on: ubuntu-latest
needs: start-ci-run-gate
if: (!(cancelled() || failure()) && needs.start-ci-run-gate.result == 'success')
steps:
- name: Checkout (Branch)
uses: actions/checkout@v4
if: github.event_name == 'push' || github.event_name == 'schedule'

- name: Checkout (PR Merge)
uses: actions/checkout@v4
if: github.event_name != 'push' && github.event_name != 'schedule'
with:
ref: "refs/pull/${{ github.event.number }}/merge"

- name: Retrieve dotnet-ef Tool Version
id: dotnet-ef-tool
run: echo "version=$(cat src/Tgstation.Server.Host/.config/dotnet-tools.json | jq -r '.tools."dotnet-ef".version')" >> $GITHUB_OUTPUT

- name: Retrieve wix Tool Version
id: wix-tool
run: echo "version=$(cat build/package/winget/.config/dotnet-tools.json | jq -r '.tools.wix.version')" >> $GITHUB_OUTPUT

- name: Retrieve dotnet-ef Nuget Version
id: dotnet-ef-nuget
run: |
regex='\s+<PackageReference Include="Microsoft.EntityFrameworkCore" Version="([1-9][0-9]*\.[0-9]+\.[0-9]+)" \/>'
if [[ $(cat src/Tgstation.Server.Host/Tgstation.Server.Host.csproj) =~ $regex ]]; then
echo "version=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
else
echo "Regex search failed!"
exit 1
fi
- name: Retrieve wix Nuget Version
id: wix-nuget
run: |
regex='<Project Sdk="WixToolset.Sdk/([1-9][0-9]*\.[0-9]+\.[0-9]+)">'
if [[ $(cat build/package/winget/Tgstation.Server.Host.Service.Wix/Tgstation.Server.Host.Service.Wix.wixproj) =~ $regex ]]; then
echo "version=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
else
echo "Regex search failed!"
exit 1
fi
- name: Fail if dotnet-ef Versions Don't Match
if: ${{ steps.dotnet-ef-tool.outputs.version != steps.dotnet-ef-nuget.outputs.version }}
run: |
echo "${{ steps.dotnet-ef-tool.outputs.version }} != ${{ steps.dotnet-ef-nuget.outputs.version }}"
exit 1
- name: Fail if wix Versions Don't Match
if: ${{ steps.wix-tool.outputs.version != steps.wix-nuget.outputs.version }}
run: |
echo "${{ steps.wix-tool.outputs.version }} != ${{ steps.wix-nuget.outputs.version }}"
exit 1
pages-build:
name: Build gh-pages
runs-on: ubuntu-latest
Expand Down Expand Up @@ -1405,7 +1463,7 @@ jobs:

ci-completion-gate: # This job exists so there isn't a moving target for branch protections
name: CI Completion Gate
needs: [ pages-build, docker-build, build-deb, build-msi, validate-openapi-spec, upload-code-coverage, check-winget-pr-template, code-scanning ]
needs: [ pages-build, docker-build, build-deb, build-msi, validate-openapi-spec, upload-code-coverage, check-winget-pr-template, code-scanning, efcore-version-match ]
runs-on: ubuntu-latest
if: (!(cancelled() || failure()) && needs.pages-build.result == 'success' && needs.docker-build.result == 'success' && needs.build-deb.result == 'success' && needs.build-msi.result == 'success' && needs.validate-openapi-spec.result == 'success' && needs.upload-code-coverage.result == 'success' && needs.check-winget-pr-template.result == 'success' && needs.code-scanning.result == 'success')
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
using Tgstation.Server.Host.Models;
using Tgstation.Server.Host.System;

using Z.EntityFramework.Plus;

namespace Tgstation.Server.Host.Components.Session
{
/// <inheritdoc />
Expand Down Expand Up @@ -221,7 +219,7 @@ await db
.ReattachInformations
.AsQueryable()
.Where(x => x.Id == result.Id)
.DeleteAsync(cancellationToken);
.ExecuteDeleteAsync(cancellationToken);
});
return null;
}
Expand Down Expand Up @@ -271,7 +269,7 @@ async ValueTask ClearImpl(IDatabaseContext databaseContext, bool instant, Cancel

if (instant)
await baseQuery
.DeleteAsync(cancellationToken);
.ExecuteDeleteAsync(cancellationToken);
else
{
var results = await baseQuery.ToListAsync(cancellationToken);
Expand Down
4 changes: 1 addition & 3 deletions src/Tgstation.Server.Host/Controllers/ChatController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
using Tgstation.Server.Host.Security;
using Tgstation.Server.Host.Utils;

using Z.EntityFramework.Plus;

namespace Tgstation.Server.Host.Controllers
{
/// <summary>
Expand Down Expand Up @@ -189,7 +187,7 @@ await Task.WhenAll(
.ChatBots
.AsQueryable()
.Where(x => x.Id == id)
.DeleteAsync(cancellationToken));
.ExecuteDeleteAsync(cancellationToken));
return null;
})

Expand Down
32 changes: 29 additions & 3 deletions src/Tgstation.Server.Host/Controllers/InstanceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,6 @@ public async ValueTask<IActionResult> Delete(long id, CancellationToken cancella
if (originalModel.Online!.Value)
return Conflict(new ErrorMessageResponse(ErrorCode.InstanceDetachOnline));

DatabaseContext.Instances.Remove(originalModel);

var originalPath = originalModel.Path!;
var attachFileName = ioManager.ConcatPath(originalPath, InstanceAttachFileName);
try
Expand All @@ -301,7 +299,35 @@ public async ValueTask<IActionResult> Delete(long id, CancellationToken cancella
throw;
}

await DatabaseContext.Save(cancellationToken); // cascades everything
try
{
// yes this is racy af. I hate it
// there's a bug where removing the root instance doesn't work sometimes
await DatabaseContext
.CompileJobs
.AsQueryable()
.Where(x => x.Job!.Instance!.Id == id)
.ExecuteDeleteAsync(cancellationToken);
await DatabaseContext
.RevInfoTestMerges
.AsQueryable()
.Where(x => x.RevisionInformation.InstanceId == id)
.ExecuteDeleteAsync(cancellationToken);
await DatabaseContext
.RevisionInformations
.AsQueryable()
.Where(x => x.InstanceId == id)
.ExecuteDeleteAsync(cancellationToken);

DatabaseContext.Instances.Remove(originalModel);
await DatabaseContext.Save(cancellationToken); // cascades everything else
}
catch
{
await ioManager.DeleteFile(attachFileName, CancellationToken.None); // DCT: Shouldn't be cancelled
throw;
}

return NoContent();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
using Tgstation.Server.Host.Security;
using Tgstation.Server.Host.Utils;

using Z.EntityFramework.Plus;

namespace Tgstation.Server.Host.Controllers
{
/// <summary>
Expand Down Expand Up @@ -259,7 +257,7 @@ public async ValueTask<IActionResult> Delete(long id, CancellationToken cancella
.Where(x => x.Id == Instance.Id)
.SelectMany(x => x.InstancePermissionSets)
.Where(x => x.PermissionSetId == id)
.DeleteAsync(cancellationToken);
.ExecuteDeleteAsync(cancellationToken);

return numDeleted > 0 ? NoContent() : this.Gone();
}
Expand Down
4 changes: 1 addition & 3 deletions src/Tgstation.Server.Host/Controllers/UserGroupController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
using Tgstation.Server.Host.Security;
using Tgstation.Server.Host.Utils;

using Z.EntityFramework.Plus;

namespace Tgstation.Server.Host.Controllers
{
/// <summary>
Expand Down Expand Up @@ -221,7 +219,7 @@ public async ValueTask<IActionResult> Delete(long id, CancellationToken cancella
.Groups
.AsQueryable()
.Where(x => x.Id == id && x.Users!.Count == 0)
.DeleteAsync(cancellationToken);
.ExecuteDeleteAsync(cancellationToken);

if (numDeleted > 0)
return NoContent();
Expand Down
18 changes: 18 additions & 0 deletions src/Tgstation.Server.Host/Database/DatabaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ public abstract class DatabaseContext : DbContext, IDatabaseContext
/// <inheritdoc />
IDatabaseCollection<RevisionInformation> IDatabaseContext.RevisionInformations => revisionInformationsCollection;

/// <inheritdoc />
IDatabaseCollection<RevInfoTestMerge> IDatabaseContext.RevInfoTestMerges => revInfoTestMergesCollection;

/// <inheritdoc />
IDatabaseCollection<TestMerge> IDatabaseContext.TestMerges => testMergesCollection;

/// <inheritdoc />
IDatabaseCollection<DreamMakerSettings> IDatabaseContext.DreamMakerSettings => dreamMakerSettingsCollection;

Expand Down Expand Up @@ -188,6 +194,16 @@ public abstract class DatabaseContext : DbContext, IDatabaseContext
/// </summary>
readonly IDatabaseCollection<RevisionInformation> revisionInformationsCollection;

/// <summary>
/// Backing field for <see cref="IDatabaseContext.RevInfoTestMerges"/>.
/// </summary>
readonly IDatabaseCollection<RevInfoTestMerge> revInfoTestMergesCollection;

/// <summary>
/// Backing field for <see cref="IDatabaseContext.TestMerges"/>.
/// </summary>
readonly IDatabaseCollection<TestMerge> testMergesCollection;

/// <summary>
/// Backing field for <see cref="IDatabaseContext.DreamMakerSettings"/>.
/// </summary>
Expand Down Expand Up @@ -267,6 +283,8 @@ protected DatabaseContext(DbContextOptions dbContextOptions)
chatBotsCollection = new DatabaseCollection<ChatBot>(ChatBots!);
chatChannelsCollection = new DatabaseCollection<ChatChannel>(ChatChannels!);
revisionInformationsCollection = new DatabaseCollection<RevisionInformation>(RevisionInformations!);
revInfoTestMergesCollection = new DatabaseCollection<RevInfoTestMerge>(RevInfoTestMerges!);
testMergesCollection = new DatabaseCollection<TestMerge>(TestMerges!);
jobsCollection = new DatabaseCollection<Job>(Jobs!);
reattachInformationsCollection = new DatabaseCollection<ReattachInformation>(ReattachInformations!);
oAuthConnections = new DatabaseCollection<OAuthConnection>(OAuthConnections!);
Expand Down
2 changes: 0 additions & 2 deletions src/Tgstation.Server.Host/Database/DatabaseSeeder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
using Tgstation.Server.Host.Security;
using Tgstation.Server.Host.System;

using Z.EntityFramework.Plus;

namespace Tgstation.Server.Host.Database
{
/// <inheritdoc />
Expand Down
10 changes: 10 additions & 0 deletions src/Tgstation.Server.Host/Database/IDatabaseContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ public interface IDatabaseContext
/// </summary>
IDatabaseCollection<RevisionInformation> RevisionInformations { get; }

/// <summary>
/// The <see cref="RevInfoTestMerge"/>s in the <see cref="IDatabaseContext"/>.
/// </summary>
IDatabaseCollection<RevInfoTestMerge> RevInfoTestMerges { get; }

/// <summary>
/// The <see cref="TestMerge"/>s in the <see cref="IDatabaseContext"/>.
/// </summary>
IDatabaseCollection<TestMerge> TestMerges { get; }

/// <summary>
/// The <see cref="Models.DreamMakerSettings"/> in the <see cref="IDatabaseContext"/>.
/// </summary>
Expand Down
2 changes: 0 additions & 2 deletions src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@
<PackageReference Include="System.Management" Version="8.0.0" />
<!-- Usage: Temporary resolution to compatibility issues with EFCore 7 and .NET 8 -->
<PackageReference Include="System.Security.Permissions" Version="8.0.0" />
<!-- Usage: .DeleteAsync() support for IQueryable<T>s -->
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="8.103.1" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit e958a50

Please sign in to comment.