Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/DistributedActors/ClusterSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,7 @@ extension ClusterSystem {
let invocation = InvocationMessage(
callID: callID,
targetIdentifier: target.identifier,
genericSubstitutions: invocation.genericSubstitutions,
arguments: arguments
)
recipient.sendInvocation(invocation)
Expand Down Expand Up @@ -1094,6 +1095,7 @@ extension ClusterSystem {
let invocation = InvocationMessage(
callID: callID,
targetIdentifier: target.identifier,
genericSubstitutions: invocation.genericSubstitutions,
arguments: arguments
)
recipient.sendInvocation(invocation)
Expand Down
3 changes: 2 additions & 1 deletion Sources/DistributedActors/InvocationBehavior.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ import struct Foundation.Data
public struct InvocationMessage: Sendable, Codable, CustomStringConvertible {
let callID: ClusterSystem.CallID
let targetIdentifier: String
let genericSubstitutions: [String]
let arguments: [Data]

var target: RemoteCallTarget {
RemoteCallTarget(targetIdentifier)
}

public var description: String {
"InvocationMessage(callID: \(callID), target: \(target), arguments: \(arguments.count))"
"InvocationMessage(callID: \(callID), target: \(target), genericSubstitutions: \(genericSubstitutions), arguments: \(arguments.count))"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import SwiftProtobuf

public struct ClusterInvocationEncoder: DistributedTargetInvocationEncoder {
public typealias SerializationRequirement = any Codable
var genericSubstitutions: [String] = []
var arguments: [Data] = []
var throwing: Bool = false

Expand All @@ -31,7 +32,8 @@ public struct ClusterInvocationEncoder: DistributedTargetInvocationEncoder {
}

public mutating func recordGenericSubstitution<T>(_ type: T.Type) throws {
fatalError("NOT IMPLEMENTED: \(#function)")
let typeName = _mangledTypeName(type) ?? _typeName(type)
self.genericSubstitutions.append(typeName)
}

public mutating func recordArgument<Value: Codable>(_ argument: RemoteCallArgument<Value>) throws {
Expand Down Expand Up @@ -72,7 +74,20 @@ public struct ClusterInvocationDecoder: DistributedTargetInvocationDecoder {
}

public mutating func decodeGenericSubstitutions() throws -> [Any.Type] {
fatalError("NOT IMPLEMENTED: \(#function)")
let genericSubstitutions: [String]
switch self.state {
case .remoteCall(_, let message):
genericSubstitutions = message.genericSubstitutions
case .localProxyCall(let invocation):
genericSubstitutions = invocation.genericSubstitutions
}

return try genericSubstitutions.map {
guard let type = _typeByName($0) else {
throw SerializationError.notAbleToDeserialize(hint: $0)
}
return type
}
}

public mutating func decodeNextArgument<Argument: Codable>() throws -> Argument {
Expand Down
23 changes: 23 additions & 0 deletions Tests/DistributedActorsTests/ClusterSystemTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,25 @@ final class ClusterSystemTests: ClusterSystemXCTestCase {
throw testKit.fail("Expected timeout to be 200 milliseconds but was \(timeoutError.timeout)")
}
}

func test_remoteCallGeneric() async throws {
let local = await setUpNode("local") { settings in
settings.enabled = true
}
let remote = await setUpNode("remote") { settings in
settings.enabled = true
}
local.cluster.join(node: remote.cluster.uniqueNode)

let greeter = Greeter(actorSystem: local)
let remoteGreeterRef = try Greeter.resolve(id: greeter.id, using: remote)

let message: String = "hello"
let value = try await shouldNotThrow {
try await remoteGreeterRef.echo(message)
}
value.shouldEqual(message)
}
}

private distributed actor Greeter {
Expand Down Expand Up @@ -414,6 +433,10 @@ private distributed actor Greeter {
try await Task.sleep(nanoseconds: delayNanos)
try await self.muted()
}

distributed func echo<T: Sendable & Codable>(_ message: T) -> T {
message
}
}

private struct GreeterCodableError: Error, Codable {}
Expand Down