Skip to content

Commit 2f7f0e5

Browse files
Copilotxperiandri
andcommitted
Fix cross-platform documentId hashing and AstExtensions List.choose
Agent-Logs-Url: https://github.com/fsprojects/FSharp.Data.GraphQL/sessions/7ce8c26c-d831-4c14-a520-93ba8f1f1622 Co-authored-by: xperiandri <2365592+xperiandri@users.noreply.github.com>
1 parent d024f22 commit 2f7f0e5

3 files changed

Lines changed: 13 additions & 16 deletions

File tree

src/FSharp.Data.GraphQL.Shared/AstExtensions.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ type Document with
328328
| None -> failwithf "Can not get information about fragment \"%s\". Fragment spread definition was not found in the query." name
329329
let operations =
330330
this.Definitions
331-
|> List_choose (function
331+
|> List.choose (function
332332
| FragmentDefinition _ -> None
333333
| OperationDefinition def -> Some def)
334334
|> List.map (fun operation -> operation.Name, operation)

src/FSharp.Data.GraphQL.Shared/Helpers/DocumentId.fs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ open System.Runtime.CompilerServices
55
open System.Security.Cryptography
66
open System.Text
77

8-
let private formatByteAsLowerHex (value : byte) =
9-
value.ToString("x2", CultureInfo.InvariantCulture)
8+
let private formatByteAsLowerHex (value : byte) = value.ToString ("x2", CultureInfo.InvariantCulture)
109

1110
/// <summary>
1211
/// Computes a deterministic document identifier from a canonical GraphQL query string.
@@ -15,9 +14,8 @@ let private formatByteAsLowerHex (value : byte) =
1514
/// <returns>A lowercase hexadecimal SHA-256 hash string that uniquely identifies the document content.</returns>
1615
[<CompiledName("FromCanonicalQuery")>]
1716
let fromCanonicalQuery (canonicalQuery : string) =
18-
let queryBytes = Encoding.UTF8.GetBytes canonicalQuery
19-
use sha256 = SHA256.Create()
17+
let normalizedCanonicalQuery = canonicalQuery.Replace("\r\n", "\n").Replace ("\r", "\n")
18+
let queryBytes = Encoding.UTF8.GetBytes normalizedCanonicalQuery
19+
use sha256 = SHA256.Create ()
2020
let hash = sha256.ComputeHash queryBytes
21-
hash
22-
|> Seq.map formatByteAsLowerHex
23-
|> String.concat ""
21+
hash |> Seq.map formatByteAsLowerHex |> String.concat ""

tests/FSharp.Data.GraphQL.Tests/ValidationCacheTests.fs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,25 +133,24 @@ let ``MemoryValidationResultCache handles concurrent access`` () : Task = task {
133133

134134
// Call cache from multiple threads simultaneously
135135
let workerCount = 10
136-
use workersReady = CountdownEvent workerCount
137-
use startGate = new ManualResetEventSlim false
136+
use workersReadyGate = new CountdownEvent (workerCount)
137+
use startGate = new ManualResetEventSlim (false)
138138

139139
let workers =
140140
[| 1..workerCount |]
141-
|> Seq.map (fun _ ->
141+
|> Array.map (fun _ ->
142142
Task.Run (fun () ->
143-
workersReady.Signal () |> ignore
143+
workersReadyGate.Signal () |> ignore
144144
startGate.Wait ()
145145
cache.GetOrAdd producer key))
146146

147-
workersReady.Wait ()
147+
workersReadyGate.Wait ()
148148
startGate.Set ()
149149
let! results = workers |> Task.WhenAll
150150

151151
// All results should be Success
152152
results |> Array.iter (fun r -> equals Success r)
153153

154-
// Producer should be called at least once, but possibly more due to race conditions
155-
// The important thing is it's not called 10 times
156-
Assert.True (callCount >= 1 && callCount < 10, $"Expected callCount between 1 and 9, got {callCount}")
154+
// Producer should be called at least once, but can run up to workerCount times due to ConcurrentDictionary.GetOrAdd factory semantics.
155+
Assert.True (callCount >= 1 && callCount <= workerCount, $"Expected callCount between 1 and {workerCount}, got {callCount}")
157156
}

0 commit comments

Comments
 (0)