Skip to content

Commit

Permalink
Merge d3f7b04 into 883cdaa
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp authored Sep 4, 2024
2 parents 883cdaa + d3f7b04 commit f2bb894
Show file tree
Hide file tree
Showing 52 changed files with 557 additions and 296 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,24 @@ private static async Task<List<TU>> CreateIterable<TU>(Func<TU, Task<TU>> execut

return responses;
}

public bool Exists(string indexName, CancellationToken cancellationToken = default) => AsyncHelper.RunSync(() => IndexExistsAsync(indexName, cancellationToken));

public async Task<bool> IndexExistsAsync(string indexName, CancellationToken cancellationToken = default)
{
try
{
await GetSettingsAsync(indexName, null, cancellationToken);
}
catch (AlgoliaApiException ex) when (ex.HttpErrorCode == 404)
{
return await Task.FromResult(false);
}
catch (Exception ex)
{
throw ex;
}

return await Task.FromResult(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,16 @@ public fun securedApiKeyRemainingValidity(apiKey: String): Duration {
val validUntil = Instant.fromEpochMilliseconds(match.groupValues[1].toLong())
return validUntil - Clock.System.now()
}

public suspend fun SearchClient.indexExists(indexName: String): Boolean {
try {
getSettings(indexName)
} catch (e: AlgoliaApiException) {
if (e.httpErrorCode == 404) {
return false
}
throw e
}

return true
}
Original file line number Diff line number Diff line change
Expand Up @@ -395,5 +395,16 @@ package object extension {
moveOperationResponse = move
)
}

def indexExists(indexName: String)(implicit ec: ExecutionContext): Future[Boolean] = {
try {
client.getSettings(indexName)
} catch {
case apiError: AlgoliaApiException if apiError.httpErrorCode == 404 => Future.successful(false)
case e: Throwable => throw e
}

Future.successful(true)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ public extension SearchClient {
batchSize: Int = 1000,
requestOptions: RequestOptions? = nil
) async throws -> ReplaceAllObjectsResponse {
let tmpIndexName = try "\(indexName)_tmp_\(Int.random(in: 1_000_000 ..< 10_000_000))"
let tmpIndexName = "\(indexName)_tmp_\(Int.random(in: 1_000_000 ..< 10_000_000))"

var copyOperationResponse = try await operationIndex(
indexName: indexName,
Expand Down Expand Up @@ -627,4 +627,14 @@ public extension SearchClient {

return timestampDate.timeIntervalSince1970 - Date().timeIntervalSince1970
}

func indexExists(indexName: String) async throws -> Bool {
do {
_ = try await self.getSettings(indexName: indexName)
} catch let AlgoliaError.httpError(error) where error.statusCode == 404 {
return false
}

return true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ public void enhanceParameters(Map<String, Object> parameters, Map<String, Object
this.enhanceParameters(parameters, bundle, null);
}

public Map<String, Object> enhanceParameter(Object param) throws CTSException, JsonMappingException, JsonProcessingException {
Map<String, Object> testOutput = createDefaultOutput();
testOutput.put("isRoot", true);
if (param == null) {
handleNull(null, testOutput);
} else if (param instanceof List || param instanceof Map) {
testOutput.put("isString", true);
testOutput.put("value", Json.mapper().writeValueAsString(param));
} else {
handlePrimitive(param, testOutput, null);
}
return testOutput;
}

/**
* @param parameters The object to traverse and annotate with type
* @param bundle The output object
Expand Down Expand Up @@ -214,13 +228,15 @@ private Map<String, Object> createDefaultOutput() {
testOutput.put("isSimpleObject", false);
testOutput.put("oneOfModel", false);
testOutput.put("isAdditionalProperty", false);
testOutput.put("isPrimitive", false);

return testOutput;
}

private void handleNull(IJsonSchemaValidationProperties spec, Map<String, Object> testOutput) {
testOutput.put("isPrimitive", true);
testOutput.put("isNull", true);
if (spec.getIsModel() || spec instanceof CodegenModel) {
if (spec != null && (spec.getIsModel() || spec instanceof CodegenModel)) {
testOutput.put("isNullObject", true);
}
}
Expand Down Expand Up @@ -458,6 +474,7 @@ private void handlePrimitive(Object param, Map<String, Object> testOutput, IJson
testOutput.put("isAnyType", true);
}
}
testOutput.put("isPrimitive", true);
testOutput.put("value", param);
}

Expand Down Expand Up @@ -522,6 +539,11 @@ private String getObjectNameForLanguage(String objectName) {
}

private String inferDataType(Object param, CodegenParameter spec, Map<String, Object> output) throws CTSException {
if (param == null) {
if (spec != null) spec.setIsNull(true);
if (output != null) output.put("isNull", true);
return "null";
}
switch (param.getClass().getSimpleName()) {
case "String":
if (spec != null) spec.setIsString(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.algolia.codegen.cts.manager.CTSManager;
import com.algolia.codegen.exceptions.CTSException;
import com.algolia.codegen.utils.*;
import io.swagger.util.Json;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -112,6 +111,7 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
stepOut.put("isGeneric", (boolean) ope.vendorExtensions.getOrDefault("x-is-generic", false));
if (ope.returnType != null && ope.returnType.length() > 0) {
stepOut.put("returnType", Helpers.toPascalCase(ope.returnType));
stepOut.put("returnsBoolean", ope.returnType.equals("Boolean")); // ruby requires a ? for boolean functions.
}

// set on testOut because we need to wrap everything for java.
Expand Down Expand Up @@ -149,6 +149,9 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
break;
case "timeouts":
stepOut.put("testTimeouts", true);
Map<String, Integer> timeouts = (Map<String, Integer>) step.expected.match;
stepOut.put("matchConnectTimeout", timeouts.get("connectTimeout"));
stepOut.put("matchResponseTimeout", timeouts.get("responseTimeout"));
break;
case "response":
stepOut.put("testResponse", true);
Expand All @@ -172,24 +175,8 @@ public void run(Map<String, CodegenModel> models, Map<String, CodegenOperation>
((String) stepOut.get("expectedError")).replace(step.method, Helpers.toPascalCase(step.method))
);
}
} else if (step.expected.match != null) {
Map<String, Object> matchMap = new HashMap<>();
if (step.expected.match instanceof Map match) {
paramsType.enhanceParameters(match, matchMap);
stepOut.put("match", matchMap);
stepOut.put("matchIsJSON", true);
} else if (step.expected.match instanceof List match) {
matchMap.put("parameters", Json.mapper().writeValueAsString(step.expected.match));
stepOut.put("match", matchMap);
stepOut.put("matchIsJSON", true);
} else {
stepOut.put("match", step.expected.match);
}
} else if (step.expected.match == null) {
stepOut.put("match", Map.of());
stepOut.put("matchIsJSON", false);
stepOut.put("matchIsNull", true);
}
stepOut.put("match", paramsType.enhanceParameter(step.expected.match));
}
steps.add(stepOut);
}
Expand Down
5 changes: 5 additions & 0 deletions scripts/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const flags = {

program.name('cli');

program.hook('preAction', () => {
// restore the cursor because sometime it's broken
process.stdout.write('\x1B[?25h');
});

program
.command('generate')
.description('Generate a specified client')
Expand Down
15 changes: 15 additions & 0 deletions scripts/cts/testServer/waitFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ function addRoutes(app: Express): void {
status: 'published',
});
});

app.get('/1/indexes/:indexName/settings', (req, res) => {
if (req.params.indexName === 'indexExistsYES') {
res.status(200).json({
attributesForFaceting: ['searchable(brand)'],
searchableAttributes: ['name', 'brand'],
customRanking: ['desc(price)', 'asc(name)'],
replicas: ['indexExistsYES-1', 'indexExistsYES-2'],
});
} else if (req.params.indexName === 'indexExistsNO') {
res.status(404).json({ message: 'Index not found' });
} else {
res.status(403).json({ message: 'Invalid API key' });
}
});
}

export function waitForApiKeyServer(): Promise<Server> {
Expand Down
2 changes: 1 addition & 1 deletion scripts/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export async function formatter(language: string, cwd: string): Promise<void> {
case 'php':
await runComposerInstall();
await run(
`PHP_CS_FIXER_IGNORE_ENV=1 php clients/algoliasearch-client-php/vendor/bin/php-cs-fixer fix ${cwd} --rules=@PhpCsFixer --using-cache=no --allow-risky=yes`,
`php clients/algoliasearch-client-php/vendor/bin/php-cs-fixer fix ${cwd} --rules=@PhpCsFixer --using-cache=no --allow-risky=yes`,
{ language },
);
break;
Expand Down
23 changes: 23 additions & 0 deletions specs/search/helpers/indexExists.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
method:
get:
x-helper: true
tags:
- Index
operationId: indexExists
summary: Check if an index exists or not
description: |
You can initialize an index with any name. The index is created on Algolia's servers when you add objects or set settings. To prevent accidentally creating new indices, or changing existing indices, you can use the exists method. The exists method returns a boolean that indicates whether an initialized index has been created.
parameters:
- in: query
name: indexName
description: The name of the index to check.
required: true
schema:
type: string
responses:
'200':
description: Index exists.
content:
application/json:
schema:
type: boolean
3 changes: 3 additions & 0 deletions specs/search/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,6 @@ paths:

/partialUpdateObjects:
$ref: 'helpers/partialUpdateObjects.yml#/method'

/indexExists:
$ref: 'helpers/indexExists.yml#/method'
45 changes: 19 additions & 26 deletions templates/csharp/tests/client/tests.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,25 @@
{{/isError}}
{{^isError}}
{{#dynamicTemplate}}{{/dynamicTemplate}}
{{#match}}
{{#testUserAgent}} {
var regexp = new Regex("{{#lambda.escapeSlash}}{{{match}}}{{/lambda.escapeSlash}}");
Assert.Matches(regexp,result.Headers["user-agent"]);
}{{/testUserAgent}}
{{#testTimeouts}}
Assert.Equal({{{match.parametersWithDataTypeMap.connectTimeout.value}}}, result.ConnectTimeout.TotalMilliseconds);
Assert.Equal({{{match.parametersWithDataTypeMap.responseTimeout.value}}}, result.ResponseTimeout.TotalMilliseconds);
{{/testTimeouts}}
{{#testHost}}
Assert.Equal("{{{match}}}", result.Host);
{{/testHost}}
{{#testResponse}}
{{#matchIsJSON}}
JsonAssert.EqualOverrideDefault("{{#lambda.escapeQuotes}}{{{match.parameters}}}{{/lambda.escapeQuotes}}", JsonSerializer.Serialize(res, JsonConfig.Options), new JsonDiffConfig(false));
{{/matchIsJSON}}
{{^matchIsJSON}}
{{#matchIsNull}}
Assert.Null(res);
{{/matchIsNull}}
{{^matchIsNull}}
Assert.Equal("{{{match}}}", res);
{{/matchIsNull}}
{{/matchIsJSON}}
{{/testResponse}}
{{/match}}
{{#testUserAgent}} {
var regexp = new Regex({{#match}}{{> tests/generateParams}}{{/match}});
Assert.Matches(regexp,result.Headers["user-agent"]);
}{{/testUserAgent}}
{{#testTimeouts}}
Assert.Equal({{{matchConnectTimeout}}}, result.ConnectTimeout.TotalMilliseconds);
Assert.Equal({{{matchResponseTimeout}}}, result.ResponseTimeout.TotalMilliseconds);
{{/testTimeouts}}
{{#testHost}}
Assert.Equal({{#match}}{{> tests/generateParams}}{{/match}}, result.Host);
{{/testHost}}
{{#testResponse}}
{{#match.isPrimitive}}
Assert.Equal({{#match}}{{> tests/generateParams}}{{/match}}, res);
{{/match.isPrimitive}}
{{^match.isPrimitive}}
JsonAssert.EqualOverrideDefault({{#match}}{{> tests/generateParams}}{{/match}}, JsonSerializer.Serialize(res, JsonConfig.Options), new JsonDiffConfig(false));
{{/match.isPrimitive}}
{{/testResponse}}
{{/isError}}
{{#times}}
}
Expand Down
2 changes: 1 addition & 1 deletion templates/csharp/tests/generateInnerParams.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
null
{{/isNull}}
{{#isString}}
"{{{value}}}"
"{{#lambda.escapeQuotes}}{{#lambda.escapeSlash}}{{{value}}}{{/lambda.escapeSlash}}{{/lambda.escapeQuotes}}"
{{/isString}}
{{#isInteger}}
{{{value}}}
Expand Down
4 changes: 2 additions & 2 deletions templates/dart/tests/client/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ void main() {
TestHandle.current.markSkipped('User agent added using an interceptor');
{{/testUserAgent}}
{{#testTimeouts}}
expect({{{match.parametersWithDataTypeMap.responseTimeout.value}}}, request.timeout.inMilliseconds);
expect({{{matchResponseTimeout}}}, request.timeout.inMilliseconds);
{{/testTimeouts}}
{{#testHost}}
expect(request.host.url, '{{{match}}}');
expect(request.host.url, {{#match}}{{> tests/param_value}}{{/match}});
{{/testHost}}
});
{{/match}}
Expand Down
14 changes: 6 additions & 8 deletions templates/dart/tests/client/method.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ try {
{{> tests/request_param}}
{{/parametersWithDataType}}
);
{{#match}}
{{#testResponse}}
{{#matchIsJSON}}
expectBody(res, """{{{match.parameters}}}""");
{{/matchIsJSON}}
{{^matchIsJSON}}
expect(res, """{{match}}""");
{{/matchIsJSON}}
{{^match.isPrimitive}}
expectBody(res, """{{{match.value}}}""");
{{/match.isPrimitive}}
{{#match.isPrimitive}}
expect(res, {{#match}}{{> tests/param_value}}{{/match}});
{{/match.isPrimitive}}
{{/testResponse}}
{{/match}}
} on InterceptionException catch (_) {
// Ignore InterceptionException
}
17 changes: 17 additions & 0 deletions templates/go/search_helpers.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -690,4 +690,21 @@ func (c *APIClient) ReplaceAllObjects(indexName string, objects []map[string]any
BatchResponses: batchResp,
MoveOperationResponse: *moveResp,
}, nil
}

// Exists returns whether an initialized index exists or not, along with a nil
// error. When encountering a network error, a non-nil error is returned along
// with false.
func (c *APIClient) IndexExists(indexName string) (bool, error) {
_, err := c.GetSettings(c.NewApiGetSettingsRequest(indexName))
if err == nil {
return true, nil
}

var apiErr *APIError
if errors.As(err, &apiErr) && apiErr.Status == http.StatusNotFound {
return false, nil
}

return false, err
}
Loading

0 comments on commit f2bb894

Please sign in to comment.