Skip to content

Commit fb23191

Browse files
committed
feat(clients): cleanup after replaceAllObjects failure
1 parent ab1b02f commit fb23191

File tree

6 files changed

+125
-2
lines changed

6 files changed

+125
-2
lines changed

scripts/cts/runCts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { startTestServer } from './testServer';
99
import { printBenchmarkReport } from './testServer/benchmark.js';
1010
import { assertChunkWrapperValid } from './testServer/chunkWrapper.js';
1111
import { assertValidReplaceAllObjects } from './testServer/replaceAllObjects.js';
12+
import { assertValidReplaceAllObjectsFailed } from './testServer/replaceAllObjectsFailed.js';
1213
import { assertValidTimeouts } from './testServer/timeout.js';
1314
import { assertValidWaitForApiKey } from './testServer/waitFor.js';
1415

@@ -152,6 +153,7 @@ export async function runCts(
152153
assertValidTimeouts(languages.length);
153154
assertChunkWrapperValid(languages.length - skip('dart') - skip('scala'));
154155
assertValidReplaceAllObjects(languages.length - skip('dart') - skip('scala'));
156+
assertValidReplaceAllObjectsFailed(languages.length - skip('dart') - skip('scala'));
155157
assertValidWaitForApiKey(languages.length - skip('dart') - skip('scala'));
156158
}
157159
if (withBenchmarkServer) {

scripts/cts/testServer/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { benchmarkServer } from './benchmark';
1111
import { chunkWrapperServer } from './chunkWrapper';
1212
import { gzipServer } from './gzip';
1313
import { replaceAllObjectsServer } from './replaceAllObjects';
14+
import { replaceAllObjectsServerFailed } from './replaceAllObjectsFailed';
1415
import { timeoutServer } from './timeout';
1516
import { timeoutServerBis } from './timeoutBis';
1617
import { waitForApiKeyServer } from './waitFor';
@@ -23,6 +24,7 @@ export async function startTestServer(suites: Record<CTSType, boolean>): Promise
2324
gzipServer(),
2425
timeoutServerBis(),
2526
replaceAllObjectsServer(),
27+
replaceAllObjectsServerFailed(),
2628
chunkWrapperServer(),
2729
waitForApiKeyServer(),
2830
apiKeyServer(),
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { Server } from 'http';
2+
3+
import { expect } from 'chai';
4+
import type { Express } from 'express';
5+
import express from 'express';
6+
7+
import { setupServer } from '.';
8+
9+
const raoState: Record<
10+
string,
11+
{
12+
tmpIndexName: string;
13+
successful: boolean;
14+
}
15+
> = {};
16+
17+
export function assertValidReplaceAllObjectsFailed(expectedCount: number): void {
18+
const count = Object.values(raoState).filter((s) => s.successful).length;
19+
if (count !== expectedCount) {
20+
throw new Error(`Expected ${expectedCount} call to replaceAllObjectsFailed, got ${count} instead.`);
21+
}
22+
}
23+
24+
function addRoutes(app: Express): void {
25+
app.use(express.urlencoded({ extended: true }));
26+
app.use(
27+
express.json({
28+
type: ['application/json', 'text/plain'], // the js client sends the body as text/plain
29+
}),
30+
);
31+
32+
app.post('/1/indexes/:indexName/operation', (req, res) => {
33+
const lang = req.params.indexName.match(/^cts_e2e_replace_all_objects_too_big_(.*)$/)?.[1] as string;
34+
raoState[lang] = {
35+
tmpIndexName: req.body.destination,
36+
successful: false,
37+
};
38+
39+
res.json({ taskID: 123, updatedAt: '2021-01-01T00:00:00.000Z' });
40+
});
41+
42+
app.post('/1/indexes/:indexName/batch', (_req, res) => {
43+
res.status(400).json({ message: 'Record is too big', status: 400 });
44+
});
45+
46+
app.delete('/1/indexes/:indexName', (req, res) => {
47+
const lang = req.params.indexName.match(/^cts_e2e_replace_all_objects_too_big_(.*)_tmp/)?.[1] as string;
48+
expect(raoState[lang].tmpIndexName).to.equal(req.params.indexName);
49+
raoState[lang].successful = true;
50+
51+
res.json({ taskID: 456, deletedAt: '2021-01-01T00:00:00.000Z' });
52+
});
53+
}
54+
55+
export function replaceAllObjectsServerFailed(): Promise<Server> {
56+
// this server is used to simulate the responses for the replaceAllObjects method, with cleanup
57+
return setupServer('replaceAllObjectsFailed', 6684, addRoutes);
58+
}

templates/Bug_report.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ body:
2727
id: client
2828
attributes:
2929
label: Client
30-
description: Which API are you targetting?
30+
description: Which API are you targeting?
3131
options:
3232
- All
3333
- AB testing

templates/go/search_helpers.mustache

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,35 +653,47 @@ func (c *APIClient) ReplaceAllObjects(indexName string, objects []map[string]any
653653
return nil, err
654654
}
655655

656-
opts = append(opts, WithWaitForTasks(true))
656+
opts = append(opts, WithWaitForTasks(true))
657657

658658
batchResp, err := c.ChunkedBatch(tmpIndexName, objects, ACTION_ADD_OBJECT, opts...)
659659
if err != nil {
660+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
661+
660662
return nil, err
661663
}
662664

663665
_, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, toIterableOptions(opts)...)
664666
if err != nil {
667+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
668+
665669
return nil, err
666670
}
667671

668672
copyResp, err = c.OperationIndex(c.NewApiOperationIndexRequest(indexName, NewOperationIndexParams(OPERATION_TYPE_COPY, tmpIndexName, WithOperationIndexParamsScope([]ScopeType{SCOPE_TYPE_SETTINGS, SCOPE_TYPE_RULES, SCOPE_TYPE_SYNONYMS}))), toRequestOptions(opts)...)
669673
if err != nil {
674+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
675+
670676
return nil, err
671677
}
672678

673679
_, err = c.WaitForTask(tmpIndexName, copyResp.TaskID, toIterableOptions(opts)...)
674680
if err != nil {
681+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
682+
675683
return nil, err
676684
}
677685

678686
moveResp, err := c.OperationIndex(c.NewApiOperationIndexRequest(tmpIndexName, NewOperationIndexParams(OPERATION_TYPE_MOVE, indexName)), toRequestOptions(opts)...)
679687
if err != nil {
688+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
689+
680690
return nil, err
681691
}
682692

683693
_, err = c.WaitForTask(tmpIndexName, moveResp.TaskID, toIterableOptions(opts)...)
684694
if err != nil {
695+
_, _ = c.DeleteIndex(c.NewApiDeleteIndexRequest(tmpIndexName))
696+
685697
return nil, err
686698
}
687699

tests/CTS/client/search/replaceAllObjects.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,54 @@
111111
}
112112
}
113113
]
114+
},
115+
{
116+
"testName": "replaceAllObjects should cleanup on failure",
117+
"autoCreateClient": false,
118+
"steps": [
119+
{
120+
"type": "createClient",
121+
"parameters": {
122+
"appId": "test-app-id",
123+
"apiKey": "test-api-key",
124+
"customHosts": [
125+
{
126+
"host": "${{localhost}}",
127+
"port": 6684
128+
}
129+
]
130+
}
131+
},
132+
{
133+
"type": "method",
134+
"method": "replaceAllObjects",
135+
"parameters": {
136+
"indexName": "cts_e2e_replace_all_objects_too_big_${{language}}",
137+
"objects": [
138+
{
139+
"objectID": "fine",
140+
"body": "small obj"
141+
},
142+
{
143+
"objectID": "toolarge",
144+
"body": "something bigger than 10KB"
145+
}
146+
]
147+
},
148+
"expected": {
149+
"error": {
150+
"csharp": "{\\\"message\\\":\\\"Record is too big\\\",\\\"status\\\":400}",
151+
"go": "API error [400] {\\\"message\\\":\\\"Record is too big\\\",\\\"status\\\":400}",
152+
"java": "Status Code: 400 - {\\\"message\\\":\\\"Record is too big\\\",\\\"status\\\":400}",
153+
"javascript": "Record is too big",
154+
"kotlin": "Client request(POST http://${{localhost}}:6684/1/indexes/cts_e2e_replace_all_objects_too_big_${{language}}/batch) invalid: 400 Bad Request. Text: \\\"{\\\"message\\\":\\\"Record is too big\\\",\\\"status\\\":400}\\\"",
155+
"php": "Record is too big",
156+
"python": "Record is too big",
157+
"ruby": "Record is too big",
158+
"swift": "HTTP error: Status code: 400 Message: Record is too big"
159+
}
160+
}
161+
}
162+
]
114163
}
115164
]

0 commit comments

Comments
 (0)