Skip to content
This repository was archived by the owner on Jan 31, 2022. It is now read-only.

Commit 541a98b

Browse files
author
Clément Le Provost
committed
Merge branch 'master' into sdk
2 parents 9340e3f + 8157983 commit 541a98b

File tree

8 files changed

+123
-16
lines changed

8 files changed

+123
-16
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
branches:
2+
only:
3+
- master
14
sudo: false # Explicitely choose container-based infrastructure, see https://docs.travis-ci.com/user/ci-environment/
25
language: android
36
jdk:

ChangeLog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Change Log
22
==========
33

4+
## 3.1 (2016-05-09)
5+
6+
- Add typed accessors for missing query parameters `filters` and `numericFilters`
7+
- Shuffle host array at init time, for better load balancing
8+
- Perform stricter check on GZip `Content-Encoding` HTTP header
9+
- Update documentation
10+
11+
412
## 3.0 (2016-04-14)
513

614
This major version brings new features as well as bug fixes. In addition, a lot of refactoring has been performed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
<!--/NO_HTML-->
66

77

8+
*Note: If you were using **version 2.x** of our Android client, read the [migration guide to version 3.x](https://github.com/algolia/algoliasearch-client-android/wiki/Migration-guide-to-version-3.x).*
9+
10+
11+
812

913

1014
<!--NO_HTML-->
@@ -22,6 +26,7 @@ Our Android client lets you easily use the [Algolia Search API](https://www.algo
2226

2327

2428

29+
2530
<!--NO_HTML-->
2631

2732
Table of Contents
@@ -1054,6 +1059,8 @@ You can also use a string array encoding (for example `numericFilters: ["price>1
10541059
<code>available=1 AND (category:Book OR NOT category:Ebook) AND public</code>
10551060
<code>date: 1441745506 TO 1441755506 AND inStock &gt; 0 AND author:&quot;John Doe&quot;</code></p>
10561061
1062+
<p>If no attribute name is specified, the filter applies to <code>_tags</code>. For example: <code>public OR user_42</code> will translate to <code>_tags:public OR _tags:user_42</code>.</p>
1063+
10571064
<p>The list of keywords is:</p>
10581065
10591066
<ul>
@@ -1141,7 +1148,7 @@ You can send multiple queries with a single API call using a batch of queries:
11411148
List<IndexQuery> queries = new ArrayList<>();
11421149

11431150
queries.add(new IndexQuery("categories", new Query(myQueryString).setHitsPerPage(3)));
1144-
queries.add(new IndexQuery("products", new Query(myQueryString).setHitsPerPage(3).setTagFilters("promotion"));
1151+
queries.add(new IndexQuery("products", new Query(myQueryString).setHitsPerPage(3).set("filters", "promotion"));
11451152
queries.add(new IndexQuery("products", new Query(myQueryString).setHitsPerPage(10)));
11461153

11471154
client.multipleQueriesAsync(queries, new CompletionHandler() {

algoliasearch/src/main/java/com/algolia/search/saas/AlgoliaException.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ public AlgoliaException(String message, int statusCode)
5050

5151
private static final long serialVersionUID = 1L;
5252

53+
/**
54+
* Get the error's HTTP status code (if any).
55+
* Only valid when the exception is an application-level error. Values are documented in the
56+
* <a href="https://www.algolia.com/doc/rest">REST API</a>.
57+
*
58+
* @return The HTTP status code, or 0 if not available.
59+
*/
5360
public int getStatusCode()
5461
{
5562
return statusCode;

algoliasearch/src/main/java/com/algolia/search/saas/Client.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import java.net.URLEncoder;
4848
import java.util.ArrayList;
4949
import java.util.Arrays;
50+
import java.util.Collections;
5051
import java.util.HashMap;
5152
import java.util.List;
5253
import java.util.Map;
@@ -64,7 +65,7 @@
6465
* </p>
6566
*/
6667
public class Client {
67-
private final static String version = "3.0";
68+
private final static String version = "3.1";
6869

6970
protected String userAgent = "Algolia for Android " + version;
7071

@@ -125,18 +126,26 @@ public Client(@NonNull String applicationID, @NonNull String apiKey, String[] ho
125126
setReadHosts(hosts);
126127
setWriteHosts(hosts);
127128
} else {
128-
setReadHosts(
129-
applicationID + "-dsn.algolia.net",
130-
applicationID + "-1.algolianet.com",
131-
applicationID + "-2.algolianet.com",
132-
applicationID + "-3.algolianet.com"
133-
);
134-
setWriteHosts(
135-
applicationID + ".algolia.net",
129+
// Initialize hosts to their default values.
130+
//
131+
// NOTE: The host list comes in two parts:
132+
//
133+
// 1. The fault-tolerant, load-balanced DNS host.
134+
// 2. The non-fault-tolerant hosts. Those hosts must be randomized to ensure proper load balancing in case
135+
// of the first host's failure.
136+
//
137+
List<String> fallbackHosts = Arrays.asList(
136138
applicationID + "-1.algolianet.com",
137139
applicationID + "-2.algolianet.com",
138140
applicationID + "-3.algolianet.com"
139141
);
142+
Collections.shuffle(fallbackHosts);
143+
readHosts = new ArrayList<>(fallbackHosts.size() + 1);
144+
readHosts.add(applicationID + "-dsn.algolia.net");
145+
readHosts.addAll(fallbackHosts);
146+
writeHosts = new ArrayList<>(fallbackHosts.size() + 1);
147+
writeHosts.add(applicationID + ".algolia.net");
148+
writeHosts.addAll(fallbackHosts);
140149
}
141150
}
142151

@@ -700,7 +709,7 @@ private byte[] _requestRaw(Method m, String url, String json, List<String> hosts
700709

701710
final byte[] rawResponse;
702711
String encoding = hostConnection.getContentEncoding();
703-
if (encoding != null && encoding.contains("gzip")) {
712+
if (encoding != null && encoding.equals("gzip")) {
704713
rawResponse = _toByteArray(new GZIPInputStream(stream));
705714
} else {
706715
rawResponse = _toByteArray(stream);

algoliasearch/src/main/java/com/algolia/search/saas/Query.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,15 @@ public JSONArray getFacetFilters() {
419419
return null;
420420
}
421421

422-
// NOTE: `filters` left out because type too complex.
422+
private static final String KEY_FILTERS = "filters";
423+
424+
public @NonNull Query setFilters(String filters) {
425+
return set(KEY_FILTERS, filters);
426+
}
427+
428+
public String getFilters() {
429+
return get(KEY_FILTERS);
430+
}
423431

424432
private static final String KEY_GET_RANKING_INFO = "getRankingInfo";
425433

@@ -688,7 +696,24 @@ public Integer getMinWordSizefor2Typos() {
688696
return parseInt(get(KEY_MIN_WORD_SIZE_FOR_2_TYPOS));
689697
}
690698

691-
// NOTE: `numericFilters` left out because type too complex.
699+
private static final String KEY_NUMERIC_FILTERS = "numericFilters";
700+
701+
public @NonNull Query setNumericFilters(JSONArray filters) {
702+
return set(KEY_NUMERIC_FILTERS, filters);
703+
}
704+
705+
public JSONArray getNumericFilters() {
706+
try {
707+
String value = get(KEY_NUMERIC_FILTERS);
708+
if (value != null) {
709+
return new JSONArray(value);
710+
}
711+
}
712+
catch (JSONException e) {
713+
// Will return null
714+
}
715+
return null;
716+
}
692717

693718
private static final String KEY_OPTIONAL_WORDS = "optionalWords";
694719

algoliasearch/src/test/java/com/algolia/search/saas/IndexTest.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ public void tearDown() throws Exception {
9696

9797
@Test
9898
public void testSearchAsync() throws Exception {
99+
testSearchAsync(Helpers.wait);
100+
}
101+
102+
public void testSearchAsync(int waitTimeout) throws Exception {
99103
// Empty search.
100104
final CountDownLatch signal = new CountDownLatch(1);
101105
index.searchAsync(new Query(), new CompletionHandler() {
@@ -109,7 +113,7 @@ public void requestCompleted(JSONObject content, AlgoliaException error) {
109113
signal.countDown();
110114
}
111115
});
112-
assertTrue("No callback was called", signal.await(Helpers.wait, TimeUnit.SECONDS));
116+
assertTrue("No callback was called", signal.await(waitTimeout, TimeUnit.SECONDS));
113117

114118
// Search with query.
115119
final CountDownLatch signal2 = new CountDownLatch(1);
@@ -124,7 +128,7 @@ public void requestCompleted(JSONObject content, AlgoliaException error) {
124128
signal2.countDown();
125129
}
126130
});
127-
assertTrue("No callback was called", signal2.await(Helpers.wait, TimeUnit.SECONDS));
131+
assertTrue("No callback was called", signal2.await(waitTimeout, TimeUnit.SECONDS));
128132
}
129133

130134
@Test
@@ -438,6 +442,26 @@ public void testHostSwitch() throws Exception {
438442
testSearchAsync();
439443
}
440444

445+
@Test
446+
public void testDNSTimeout() throws Exception {
447+
// Given first host resulting in a DNS Timeout
448+
String appId = (String) Whitebox.getInternalState(client, "applicationID");
449+
List<String> hostsArray = (List<String>) Whitebox.getInternalState(client, "readHosts");
450+
hostsArray.set(0, appId + "-dsn.algolia.biz");
451+
Whitebox.setInternalState(client, "readHosts", hostsArray);
452+
453+
//And an index that does not cache search queries
454+
index.disableSearchCache();
455+
456+
457+
// Expect successful search within 5 seconds
458+
long startTime = System.nanoTime();
459+
testSearchAsync(5);
460+
final long duration = (System.nanoTime() - startTime) / 1000000;
461+
462+
// Which should take at least 2 seconds, as per Client.connectTimeout
463+
assertTrue("We should first timeout before successfully searching, but test took only " + duration + " ms.", duration > 2000);
464+
}
441465

442466
@Test
443467
public void testSNI() throws Exception {
@@ -544,7 +568,7 @@ public void testDeleteByQueryAsync() throws Exception {
544568
final CountDownLatch signal = new CountDownLatch(2);
545569
addDummyObjects(3000);
546570
final Query query = new Query();
547-
query.set("numericFilters", "dummy < 1500");
571+
query.setNumericFilters(new JSONArray().put("dummy < 1500"));
548572
index.deleteByQueryAsync(query, new CompletionHandler() {
549573
@Override
550574
public void requestCompleted(JSONObject content, AlgoliaException error) {

algoliasearch/src/test/java/com/algolia/search/saas/QueryTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,4 +598,28 @@ public void test_minimumAroundRadius() {
598598
Query query2 = Query.parse(query1.build());
599599
assertEquals(query2.getMinimumAroundRadius(), query1.getMinimumAroundRadius());
600600
}
601+
602+
@Test
603+
public void test_numericFilters() throws JSONException {
604+
final JSONArray VALUE = new JSONArray("[\"code=1\", [\"price:0 to 10\", \"price:1000 to 2000\"]]");
605+
Query query1 = new Query();
606+
assertNull(query1.getNumericFilters());
607+
query1.setNumericFilters(VALUE);
608+
assertEquals(query1.getNumericFilters(), VALUE);
609+
assertEquals(query1.get("numericFilters"), "[\"code=1\",[\"price:0 to 10\",\"price:1000 to 2000\"]]");
610+
Query query2 = Query.parse(query1.build());
611+
assertEquals(query2.getNumericFilters(), query1.getNumericFilters());
612+
}
613+
614+
@Test
615+
public void test_filters() {
616+
final String VALUE = "available=1 AND (category:Book OR NOT category:Ebook) AND publication_date: 1441745506 TO 1441755506 AND inStock > 0 AND author:\"John Doe\"";
617+
Query query1 = new Query();
618+
assertNull(query1.getFilters());
619+
query1.setFilters(VALUE);
620+
assertEquals(query1.getFilters(), VALUE);
621+
assertEquals(query1.get("filters"), VALUE);
622+
Query query2 = Query.parse(query1.build());
623+
assertEquals(query2.getFilters(), query1.getFilters());
624+
}
601625
}

0 commit comments

Comments
 (0)