Skip to content

Commit cc5efc4

Browse files
committed
Expose Response on GetTaskResponse (#3966)
* Expose Response on GetTaskResponse This commit exposes Response on GetTaskResponse. Response is the response object for the action performed by the Task, so will vary by action. For this reason, expose Response as an internal LazyDocument, with a method to retrieve a TResponse from the deserialized LazyDocument bytes. * Deserialize response with RequestResponseSerializer This commit updates the GetResponse<T>() impl on GetTaskResponse to use the RequestResponseDeserializer when deserializing the LazyDocument. This is exposed as an internal method only. Remove LazyDocument ctor overloads that are superfluous. Closes #3963 (cherry picked from commit ba5b1b1)
1 parent 3da50b6 commit cc5efc4

File tree

3 files changed

+123
-16
lines changed

3 files changed

+123
-16
lines changed

src/Nest/Cluster/TaskManagement/GetTask/GetTaskResponse.cs

+11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.Serialization;
2+
using Elasticsearch.Net;
23

34
namespace Nest
45
{
@@ -9,5 +10,15 @@ public class GetTaskResponse : ResponseBase
910

1011
[DataMember(Name = "task")]
1112
public TaskInfo Task { get; internal set; }
13+
14+
[DataMember(Name = "response")]
15+
internal LazyDocument Response { get; set; }
16+
17+
/// <summary>
18+
/// Gets the response for the request that the task represents, if available.
19+
/// Because the response will have no associated <see cref="ApiCallDetails"/>, the value
20+
/// of <see cref="IResponse.IsValid"/> should not be used.
21+
/// </summary>
22+
public TResponse GetResponse<TResponse>() where TResponse : class, IResponse => Response?.AsUsingRequestResponseSerializer<TResponse>();
1223
}
1324
}

src/Nest/CommonAbstractions/LazyDocument/LazyDocument.cs

+18-16
Original file line numberDiff line numberDiff line change
@@ -45,51 +45,53 @@ public interface ILazyDocument
4545
[JsonFormatter(typeof(LazyDocumentFormatter))]
4646
public class LazyDocument : ILazyDocument
4747
{
48-
private readonly IElasticsearchSerializer _serializer;
48+
private readonly IElasticsearchSerializer _sourceSerializer;
49+
private readonly IElasticsearchSerializer _requestResponseSerializer;
4950
private readonly IMemoryStreamFactory _memoryStreamFactory;
5051

51-
internal LazyDocument(byte[] bytes, IJsonFormatterResolver formatterResolver)
52-
: this(bytes, formatterResolver.GetConnectionSettings()) { }
53-
54-
private LazyDocument(byte[] bytes, IConnectionSettingsValues settings) :
55-
this(bytes, settings.SourceSerializer, settings.MemoryStreamFactory) { }
56-
57-
private LazyDocument(byte[] bytes, IElasticsearchSerializer serializer, IMemoryStreamFactory memoryStreamFactory)
52+
internal LazyDocument(byte[] bytes, IJsonFormatterResolver formatterResolver)
5853
{
5954
Bytes = bytes;
60-
_serializer = serializer;
61-
_memoryStreamFactory = memoryStreamFactory;
55+
var settings = formatterResolver.GetConnectionSettings();
56+
_sourceSerializer = settings.SourceSerializer;
57+
_requestResponseSerializer = settings.RequestResponseSerializer;
58+
_memoryStreamFactory = settings.MemoryStreamFactory;
6259
}
6360

64-
6561
internal byte[] Bytes { get; }
6662

63+
internal T AsUsingRequestResponseSerializer<T>()
64+
{
65+
using (var ms = _memoryStreamFactory.Create(Bytes))
66+
return _requestResponseSerializer.Deserialize<T>(ms);
67+
}
68+
6769
/// <inheritdoc />
6870
public T As<T>()
6971
{
7072
using (var ms = _memoryStreamFactory.Create(Bytes))
71-
return _serializer.Deserialize<T>(ms);
73+
return _sourceSerializer.Deserialize<T>(ms);
7274
}
7375

7476
/// <inheritdoc />
7577
public object As(Type objectType)
7678
{
7779
using (var ms = _memoryStreamFactory.Create(Bytes))
78-
return _serializer.Deserialize(objectType, ms);
80+
return _sourceSerializer.Deserialize(objectType, ms);
7981
}
80-
82+
8183
/// <inheritdoc />
8284
public Task<T> AsAsync<T>(CancellationToken ct = default)
8385
{
8486
using (var ms = _memoryStreamFactory.Create(Bytes))
85-
return _serializer.DeserializeAsync<T>(ms, ct);
87+
return _sourceSerializer.DeserializeAsync<T>(ms, ct);
8688
}
8789

8890
/// <inheritdoc />
8991
public Task<object> AsAsync(Type objectType, CancellationToken ct = default)
9092
{
9193
using (var ms = _memoryStreamFactory.Create(Bytes))
92-
return _serializer.DeserializeAsync(objectType, ms, ct);
94+
return _sourceSerializer.DeserializeAsync(objectType, ms, ct);
9395
}
9496
}
9597
}

src/Tests/Tests/Cluster/TaskManagement/GetTask/GetTaskApiTests.cs

+94
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Threading;
23
using Elasticsearch.Net;
34
using FluentAssertions;
45
using Nest;
@@ -79,4 +80,97 @@ protected override void IntegrationSetup(IElasticClient client, CallUniqueValues
7980
_taskId = response.Task;
8081
}
8182
}
83+
84+
/// <summary>
85+
/// Similar to GetTaskApiTests, except the test is not performed until after the task is completed,
86+
/// so that the response to which the task relates is available on GetTaskResponse
87+
/// </summary>
88+
public class GetTaskApiCompletedTaskTests : GetTaskApiTests
89+
{
90+
private static TaskId _taskId = new TaskId("fakeid:1");
91+
92+
public GetTaskApiCompletedTaskTests(WritableCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
93+
94+
protected override bool ExpectIsValid => true;
95+
protected override int ExpectStatusCode => 200;
96+
97+
protected override Func<GetTaskDescriptor, IGetTaskRequest> Fluent => s => s;
98+
protected override HttpMethod HttpMethod => HttpMethod.GET;
99+
100+
protected override GetTaskRequest Initializer => new GetTaskRequest(_taskId);
101+
protected override string UrlPath => $"/_tasks/fakeid%3A1";
102+
103+
protected override LazyResponses ClientUsage() => Calls(
104+
(client, f) => client.Tasks.GetTask(_taskId, f),
105+
(client, f) => client.Tasks.GetTaskAsync(_taskId, f),
106+
(client, r) => client.Tasks.GetTask(r),
107+
(client, r) => client.Tasks.GetTaskAsync(r)
108+
);
109+
110+
protected override GetTaskDescriptor NewDescriptor() => new GetTaskDescriptor(_taskId);
111+
112+
protected override void ExpectResponse(GetTaskResponse response)
113+
{
114+
response.ShouldBeValid();
115+
response.Task.Should().NotBeNull();
116+
response.Completed.Should().BeTrue();
117+
118+
var task = response.Task;
119+
task.Node.Should().NotBeNullOrEmpty();
120+
task.Id.Should().BeGreaterThan(0);
121+
task.Type.Should().Be("transport");
122+
task.Action.Should().Be("indices:data/write/reindex");
123+
task.Status.Should().NotBeNull();
124+
task.StartTimeInMilliseconds.Should().BeGreaterThan(0);
125+
task.RunningTimeInNanoseconds.Should().BeGreaterThan(0);
126+
task.Cancellable.Should().BeTrue();
127+
128+
var reindexResponse = response.GetResponse<ReindexOnServerResponse>();
129+
reindexResponse.Should().NotBeNull();
130+
reindexResponse.Took.Should().BeGreaterThan(0);
131+
reindexResponse.Failures.Should().BeEmpty();
132+
}
133+
134+
protected override void IntegrationSetup(IElasticClient client, CallUniqueValues values)
135+
{
136+
// get a suitable load of projects in order to get a decent task status out
137+
var sourceIndex = "project-get-completed-task";
138+
var targetIndex = "tasks-lists-completed-get";
139+
var bulkResponse = client.IndexMany(Project.Generator.Generate(500), sourceIndex);
140+
if (!bulkResponse.IsValid)
141+
throw new Exception("failure in setting up integration");
142+
143+
var createIndex = client.Indices.Create(targetIndex, i => i
144+
.Settings(settings => settings.Analysis(DefaultSeeder.ProjectAnalysisSettings))
145+
.Map<Project>(DefaultSeeder.ProjectTypeMappings)
146+
);
147+
createIndex.ShouldBeValid();
148+
149+
var response = client.ReindexOnServer(r => r
150+
.Source(s => s.Index(sourceIndex))
151+
.Destination(d => d
152+
.Index(targetIndex)
153+
.OpType(OpType.Create)
154+
)
155+
.Conflicts(Conflicts.Proceed)
156+
.WaitForCompletion(false)
157+
.Refresh()
158+
);
159+
160+
_taskId = response.Task;
161+
162+
// poll until task is complete
163+
var getTaskResponse = client.Tasks.GetTask(_taskId);
164+
var completed = getTaskResponse.Completed;
165+
while (!completed)
166+
{
167+
Thread.Sleep(2000);
168+
getTaskResponse = client.Tasks.GetTask(_taskId);
169+
if (getTaskResponse.IsValid)
170+
completed = getTaskResponse.Completed;
171+
else
172+
throw new Exception($"problem setting up completed task: {getTaskResponse.DebugInformation}");
173+
}
174+
}
175+
}
82176
}

0 commit comments

Comments
 (0)