From 8d5a9698e76785dd3f2f40ab800ac69c10df0bdb Mon Sep 17 00:00:00 2001 From: JOSE FUXA <9057699+j-fuxa@users.noreply.github.com> Date: Sat, 23 Aug 2025 19:09:27 -0400 Subject: [PATCH] Changed: Fixed large buffer rent caused by the default implementation of Stream.Read(Span) Removed: qodana.yml Signed-off-by: JOSE FUXA <9057699+j-fuxa@users.noreply.github.com> --- .editorconfig | 12 +++++++-- .github/workflows/qodana.yml | 27 ------------------- .github/workflows/release.yml | 11 ++++++-- .gitignore | 2 +- EventStore.Plugins.sln | 1 - .../EventStore.Plugins.csproj | 13 ++++++--- .../Transforms/ChunkDataReadStream.cs | 21 ++++++++++++--- .../Transforms/ChunkDataWriteStream.cs | 7 ++++- 8 files changed, 52 insertions(+), 42 deletions(-) delete mode 100644 .github/workflows/qodana.yml diff --git a/.editorconfig b/.editorconfig index 95c774b..982feed 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,4 @@ -# EditorConfig is awesome: -http://EditorConfig.org +# EditorConfig is awesome: http://EditorConfig.org # top-most EditorConfig file root = true @@ -12,6 +11,8 @@ trim_trailing_whitespace = true # C# files [*.cs] +charset = utf-8 + # New line preferences csharp_new_line_before_open_brace = none csharp_new_line_before_catch = false @@ -21,6 +22,13 @@ csharp_new_line_before_members_in_anonymous_types = false csharp_new_line_before_members_in_object_initializers = false csharp_new_line_within_query_expression_clauses = true +# use file-scoped namespaces +csharp_style_namespace_declarations = file_scoped +dotnet_diagnostic.IDE0161.severity = error + +# use ValueTasks correctly +dotnet_diagnostic.CA2012.severity = error + # Indentation preferences csharp_indent_block_contents = true csharp_indent_braces = false diff --git a/.github/workflows/qodana.yml b/.github/workflows/qodana.yml deleted file mode 100644 index e929b56..0000000 --- a/.github/workflows/qodana.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Qodana -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - - master - - 'release/*' - -jobs: - qodana: - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - checks: write - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit - fetch-depth: 0 # a full history is required for pull request analysis - submodules: recursive - - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2024.1 - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c64ecc..cb65435 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,6 +3,11 @@ on: push: tags: - "v*" + +permissions: + contents: read + packages: write + jobs: release: runs-on: ubuntu-latest @@ -17,12 +22,14 @@ jobs: - name: Get the version id: get_version - run: echo "version=${GITHUB_REF:11}" >> $GITHUB_OUTPUT + run: | + echo "version=${GITHUB_REF:11}" >> $GITHUB_OUTPUT + echo "version: ${{ steps.get_version.outputs.version }}" - name: Build, Pack and Publish run: | dotnet pack /p:Version=${{ steps.get_version.outputs.version }} -o artefacts -c Release src/EventStore.Plugins/EventStore.Plugins.csproj - dotnet nuget push artefacts/EventStore.Plugins.${{ steps.get_version.outputs.version }}.nupkg -k ${{ secrets.nugetkey }} -s https://api.nuget.org/v3/index.json + dotnet nuget push artefacts/EventStore.Plugins.${{ steps.get_version.outputs.version }}.nupkg -k ${{ secrets.GITHUB_TOKEN }} -s https://nuget.pkg.github.com/TrogonStack/index.json - name: Create Release id: create_release uses: actions/create-release@v1 diff --git a/.gitignore b/.gitignore index d32c6ff..e5592be 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,7 @@ ipch/ *.DotSettings *.DotSettings.user *.DotSettings.personal/Logs -*.md + !CHANGELOG.md /Data /src/Public/v8/ diff --git a/EventStore.Plugins.sln b/EventStore.Plugins.sln index bd86634..3f375b9 100644 --- a/EventStore.Plugins.sln +++ b/EventStore.Plugins.sln @@ -12,7 +12,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore LICENSE.md = LICENSE.md - NOTICE.md = NOTICE.md qodana.yaml = qodana.yaml README.md = README.md EndProjectSection diff --git a/src/EventStore.Plugins/EventStore.Plugins.csproj b/src/EventStore.Plugins/EventStore.Plugins.csproj index 18e705f..6a2b73d 100644 --- a/src/EventStore.Plugins/EventStore.Plugins.csproj +++ b/src/EventStore.Plugins/EventStore.Plugins.csproj @@ -8,7 +8,7 @@ enable true - + EventStore.Plugins Event Store Ltd @@ -21,7 +21,12 @@ Copyright 2012-2024 Event Store Ltd eventstore plugins - + + + https://github.com/TrogonStack/TrogonEventStore.Plugins + git + + @@ -29,11 +34,11 @@ - + - + diff --git a/src/EventStore.Plugins/Transforms/ChunkDataReadStream.cs b/src/EventStore.Plugins/Transforms/ChunkDataReadStream.cs index 2a880b8..63d878b 100644 --- a/src/EventStore.Plugins/Transforms/ChunkDataReadStream.cs +++ b/src/EventStore.Plugins/Transforms/ChunkDataReadStream.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.Runtime.CompilerServices; namespace EventStore.Plugins.Transforms; @@ -10,12 +9,26 @@ public class ChunkDataReadStream(Stream chunkFileStream) : Stream { public sealed override bool CanSeek => true; public sealed override bool CanWrite => false; public sealed override void Write(byte[] buffer, int offset, int count) => throw new InvalidOperationException(); + public override void Write(ReadOnlySpan buffer) => throw new InvalidOperationException(); + public sealed override void WriteByte(byte value) => throw new InvalidOperationException(); + public sealed override void Flush() => throw new InvalidOperationException(); public sealed override void SetLength(long value) => throw new InvalidOperationException(); public override long Length => throw new NotSupportedException(); - // reads must always return exactly `count` bytes as we never read past the (flushed) writer checkpoint - public override int Read(byte[] buffer, int offset, int count) => ChunkFileStream.Read(buffer, offset, count); + public sealed override int Read(byte[] buffer, int offset, int count) { + ValidateBufferArguments(buffer, offset, count); + + return Read(buffer.AsSpan(offset, count)); + } + + // reads must always return exactly `Span.Length` bytes as we never read past the (flushed) writer checkpoint + public override int Read(Span buffer) => ChunkFileStream.Read(buffer); + + public sealed override int ReadByte() { + Unsafe.SkipInit(out byte value); + return Read(new(ref value)) is 1 ? value : -1; + } // seeks need to support only `SeekOrigin.Begin` public override long Seek(long offset, SeekOrigin origin) { diff --git a/src/EventStore.Plugins/Transforms/ChunkDataWriteStream.cs b/src/EventStore.Plugins/Transforms/ChunkDataWriteStream.cs index 1f82195..4e6e50e 100644 --- a/src/EventStore.Plugins/Transforms/ChunkDataWriteStream.cs +++ b/src/EventStore.Plugins/Transforms/ChunkDataWriteStream.cs @@ -12,6 +12,9 @@ public class ChunkDataWriteStream(Stream chunkFileStream, HashAlgorithm checksum public sealed override bool CanSeek => false; public sealed override bool CanWrite => true; public sealed override int Read(byte[] buffer, int offset, int count) => throw new InvalidOperationException(); + public sealed override int Read(Span buffer) => throw new InvalidOperationException(); + public sealed override int ReadByte() => throw new InvalidOperationException(); + public sealed override long Seek(long offset, SeekOrigin origin) => throw new InvalidOperationException(); public override void Write(byte[] buffer, int offset, int count) { @@ -22,6 +25,7 @@ public override void Write(byte[] buffer, int offset, int count) { public override void Flush() => ChunkFileStream.Flush(); public override void SetLength(long value) => ChunkFileStream.SetLength(value); public override long Length => ChunkFileStream.Length; + public override long Position { get => ChunkFileStream.Position; set { @@ -31,7 +35,8 @@ public override long Position { ReadAndChecksum(value); if (ChunkFileStream.Position != value) - throw new Exception($"Writer's position ({ChunkFileStream.Position:N0}) is not at the expected position ({value:N0})"); + throw new Exception( + $"Writer's position ({ChunkFileStream.Position:N0}) is not at the expected position ({value:N0})"); } }