Use TimeToLive (TimeSpan?) instead of TtlMs (long?) in public APIs (#1644)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: PranavSenthilnathan <12225508+PranavSenthilnathan@users.noreply.github.com> Co-authored-by: halter73 <54385+halter73@users.noreply.github.com> Co-authored-by: Pranav Senthilnathan <pranas@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
9ba1f47d77
commit
3368bb7349
10 changed files with 30 additions and 85 deletions
|
|
@ -827,13 +827,6 @@
|
|||
<Right>lib/net10.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.get_TimeToLive</Target>
|
||||
<Left>lib/net10.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net10.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_PollInterval(System.Nullable{System.TimeSpan})</Target>
|
||||
|
|
@ -848,13 +841,6 @@
|
|||
<Right>lib/net10.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_TimeToLive(System.Nullable{System.TimeSpan})</Target>
|
||||
<Left>lib/net10.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net10.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.ServerCapabilities.get_Tasks</Target>
|
||||
|
|
@ -1212,13 +1198,6 @@
|
|||
<Right>lib/net8.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.get_TimeToLive</Target>
|
||||
<Left>lib/net8.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net8.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_PollInterval(System.Nullable{System.TimeSpan})</Target>
|
||||
|
|
@ -1233,13 +1212,6 @@
|
|||
<Right>lib/net8.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_TimeToLive(System.Nullable{System.TimeSpan})</Target>
|
||||
<Left>lib/net8.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net8.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.ServerCapabilities.get_Tasks</Target>
|
||||
|
|
@ -1597,13 +1569,6 @@
|
|||
<Right>lib/net9.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.get_TimeToLive</Target>
|
||||
<Left>lib/net9.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net9.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_PollInterval(System.Nullable{System.TimeSpan})</Target>
|
||||
|
|
@ -1618,13 +1583,6 @@
|
|||
<Right>lib/net9.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_TimeToLive(System.Nullable{System.TimeSpan})</Target>
|
||||
<Left>lib/net9.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/net9.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.ServerCapabilities.get_Tasks</Target>
|
||||
|
|
@ -1982,13 +1940,6 @@
|
|||
<Right>lib/netstandard2.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.get_TimeToLive</Target>
|
||||
<Left>lib/netstandard2.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/netstandard2.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_PollInterval(System.Nullable{System.TimeSpan})</Target>
|
||||
|
|
@ -2003,13 +1954,6 @@
|
|||
<Right>lib/netstandard2.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.GetTaskResult.set_TimeToLive(System.Nullable{System.TimeSpan})</Target>
|
||||
<Left>lib/netstandard2.0/ModelContextProtocol.Core.dll</Left>
|
||||
<Right>lib/netstandard2.0/ModelContextProtocol.Core.dll</Right>
|
||||
<IsBaselineSuppression>true</IsBaselineSuppression>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:ModelContextProtocol.Protocol.ServerCapabilities.get_Tasks</Target>
|
||||
|
|
|
|||
|
|
@ -55,10 +55,11 @@ public sealed class CreateTaskResult : Result
|
|||
public required DateTimeOffset LastUpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live duration from creation in milliseconds, or <see langword="null"/> for unlimited.
|
||||
/// Gets or sets the time-to-live duration from creation, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ttlMs")]
|
||||
public long? TtlMs { get; set; }
|
||||
[JsonConverter(typeof(TimeSpanMillisecondsConverter))]
|
||||
public TimeSpan? TimeToLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suggested polling interval in milliseconds.
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@ public abstract class GetTaskResult : Result
|
|||
public required DateTimeOffset LastUpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live duration from creation in milliseconds, or <see langword="null"/> for unlimited.
|
||||
/// Gets or sets the time-to-live duration from creation, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ttlMs")]
|
||||
public long? TtlMs { get; set; }
|
||||
public TimeSpan? TimeToLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suggested polling interval in milliseconds.
|
||||
|
|
@ -245,7 +245,7 @@ public abstract class GetTaskResult : Result
|
|||
};
|
||||
|
||||
taskResult.StatusMessage = statusMessage;
|
||||
taskResult.TtlMs = ttlMs;
|
||||
taskResult.TimeToLive = ttlMs is null ? null : TimeSpan.FromMilliseconds(ttlMs.Value);
|
||||
taskResult.PollIntervalMs = pollIntervalMs;
|
||||
taskResult.ResultType = resultType;
|
||||
taskResult.Meta = meta;
|
||||
|
|
@ -287,9 +287,9 @@ public abstract class GetTaskResult : Result
|
|||
writer.WriteString("createdAt", value.CreatedAt);
|
||||
writer.WriteString("lastUpdatedAt", value.LastUpdatedAt);
|
||||
|
||||
if (value.TtlMs is not null)
|
||||
if (value.TimeToLive is not null)
|
||||
{
|
||||
writer.WriteNumber("ttlMs", value.TtlMs.Value);
|
||||
writer.WriteNumber("ttlMs", (long)value.TimeToLive.Value.TotalMilliseconds);
|
||||
}
|
||||
|
||||
if (value.PollIntervalMs is not null)
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ public abstract class TaskStatusNotificationParams : NotificationParams
|
|||
public required DateTimeOffset LastUpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time-to-live duration from creation in milliseconds, or <see langword="null"/> for unlimited.
|
||||
/// Gets or sets the time-to-live duration from creation, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
[JsonPropertyName("ttlMs")]
|
||||
public long? TtlMs { get; set; }
|
||||
public TimeSpan? TimeToLive { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the suggested polling interval in milliseconds.
|
||||
|
|
@ -247,7 +247,7 @@ public abstract class TaskStatusNotificationParams : NotificationParams
|
|||
};
|
||||
|
||||
notification.StatusMessage = statusMessage;
|
||||
notification.TtlMs = ttlMs;
|
||||
notification.TimeToLive = ttlMs is null ? null : TimeSpan.FromMilliseconds(ttlMs.Value);
|
||||
notification.PollIntervalMs = pollIntervalMs;
|
||||
notification.Meta = meta;
|
||||
|
||||
|
|
@ -283,9 +283,9 @@ public abstract class TaskStatusNotificationParams : NotificationParams
|
|||
writer.WriteString("createdAt", value.CreatedAt);
|
||||
writer.WriteString("lastUpdatedAt", value.LastUpdatedAt);
|
||||
|
||||
if (value.TtlMs is not null)
|
||||
if (value.TimeToLive is not null)
|
||||
{
|
||||
writer.WriteNumber("ttlMs", value.TtlMs.Value);
|
||||
writer.WriteNumber("ttlMs", (long)value.TimeToLive.Value.TotalMilliseconds);
|
||||
}
|
||||
|
||||
if (value.PollIntervalMs is not null)
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ public class InMemoryMcpTaskStore : IMcpTaskStore
|
|||
public long DefaultPollIntervalMs { get; set; } = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the default time-to-live in milliseconds for new tasks, or <see langword="null"/> for unlimited.
|
||||
/// Gets or sets the default time-to-live for new tasks, or <see langword="null"/> for unlimited.
|
||||
/// </summary>
|
||||
public long? DefaultTtlMs { get; set; }
|
||||
public TimeSpan? DefaultTimeToLive { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<McpTaskInfo> CreateTaskAsync(CancellationToken cancellationToken = default)
|
||||
|
|
@ -42,7 +42,7 @@ public class InMemoryMcpTaskStore : IMcpTaskStore
|
|||
var taskId = Guid.NewGuid().ToString("N");
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
|
||||
var info = new McpTaskInfo(taskId, McpTaskStatus.Working, now, now, DefaultTtlMs, DefaultPollIntervalMs);
|
||||
var info = new McpTaskInfo(taskId, McpTaskStatus.Working, now, now, DefaultTimeToLive, DefaultPollIntervalMs);
|
||||
_tasks[taskId] = info;
|
||||
|
||||
return Task.FromResult(info);
|
||||
|
|
|
|||
|
|
@ -1023,7 +1023,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
Status = info.Status,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
ResultType = "task",
|
||||
|
|
@ -1036,7 +1036,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
TaskId = info.TaskId,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
ResultType = "complete",
|
||||
|
|
@ -1046,7 +1046,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
TaskId = info.TaskId,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
Result = info.Result ?? throw new InvalidOperationException($"Task '{info.TaskId}' is completed but has no result."),
|
||||
|
|
@ -1057,7 +1057,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
TaskId = info.TaskId,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
Error = info.Error ?? throw new InvalidOperationException($"Task '{info.TaskId}' is failed but has no error."),
|
||||
|
|
@ -1068,7 +1068,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
TaskId = info.TaskId,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
ResultType = "complete",
|
||||
|
|
@ -1078,7 +1078,7 @@ internal sealed partial class McpServerImpl : McpServer
|
|||
TaskId = info.TaskId,
|
||||
CreatedAt = info.CreatedAt,
|
||||
LastUpdatedAt = info.LastUpdatedAt,
|
||||
TtlMs = info.TtlMs,
|
||||
TimeToLive = info.TimeToLive,
|
||||
PollIntervalMs = info.PollIntervalMs,
|
||||
StatusMessage = info.StatusMessage,
|
||||
// McpTaskInfo.InputRequests is IReadOnlyDictionary (covers immutable store
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public sealed record McpTaskInfo(
|
|||
McpTaskStatus Status,
|
||||
DateTimeOffset CreatedAt,
|
||||
DateTimeOffset LastUpdatedAt,
|
||||
long? TtlMs = null,
|
||||
TimeSpan? TimeToLive = null,
|
||||
long? PollIntervalMs = null,
|
||||
string? StatusMessage = null,
|
||||
JsonElement? Result = null,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public static class TaskSerializationTests
|
|||
StatusMessage = "Processing...",
|
||||
CreatedAt = new DateTimeOffset(2025, 6, 1, 12, 0, 0, TimeSpan.Zero),
|
||||
LastUpdatedAt = new DateTimeOffset(2025, 6, 1, 12, 5, 0, TimeSpan.Zero),
|
||||
TtlMs = 3600000,
|
||||
TimeToLive = TimeSpan.FromHours(1),
|
||||
PollIntervalMs = 5000,
|
||||
ResultType = "task",
|
||||
Meta = new JsonObject { ["key"] = "value" }
|
||||
|
|
@ -36,7 +36,7 @@ public static class TaskSerializationTests
|
|||
Assert.Equal("Processing...", deserialized.StatusMessage);
|
||||
Assert.Equal(original.CreatedAt, deserialized.CreatedAt);
|
||||
Assert.Equal(original.LastUpdatedAt, deserialized.LastUpdatedAt);
|
||||
Assert.Equal(3600000, deserialized.TtlMs);
|
||||
Assert.Equal(TimeSpan.FromHours(1), deserialized.TimeToLive);
|
||||
Assert.Equal(5000, deserialized.PollIntervalMs);
|
||||
Assert.Equal("task", deserialized.ResultType);
|
||||
Assert.NotNull(deserialized.Meta);
|
||||
|
|
@ -52,7 +52,7 @@ public static class TaskSerializationTests
|
|||
Status = McpTaskStatus.Working,
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
LastUpdatedAt = DateTimeOffset.UtcNow,
|
||||
TtlMs = 60000,
|
||||
TimeToLive = TimeSpan.FromMinutes(1),
|
||||
PollIntervalMs = 1000,
|
||||
ResultType = "task",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,13 +55,13 @@ public class InMemoryMcpTaskStoreTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateTaskAsync_UsesDefaultTtl()
|
||||
public async Task CreateTaskAsync_UsesDefaultTimeToLive()
|
||||
{
|
||||
var store = new InMemoryMcpTaskStore { DefaultTtlMs = 30000 };
|
||||
var store = new InMemoryMcpTaskStore { DefaultTimeToLive = TimeSpan.FromSeconds(30) };
|
||||
|
||||
var result = await store.CreateTaskAsync(CT);
|
||||
|
||||
Assert.Equal(30000, result.TtlMs);
|
||||
Assert.Equal(TimeSpan.FromSeconds(30), result.TimeToLive);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public class TaskCancellationIntegrationTests : ClientServerTestBase
|
|||
options.TaskStore = new InMemoryMcpTaskStore
|
||||
{
|
||||
DefaultPollIntervalMs = 50,
|
||||
DefaultTtlMs = 5000,
|
||||
DefaultTimeToLive = TimeSpan.FromSeconds(5),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue