embulk-output-elasticsearch 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/build.gradle +3 -3
- data/src/main/java/org/embulk/output/elasticsearch/ElasticsearchHttpClient.java +95 -69
- data/src/main/java/org/embulk/output/elasticsearch/ElasticsearchOutputPluginDelegate.java +15 -48
- data/src/main/java/org/embulk/output/elasticsearch/ElasticsearchRecordBuffer.java +16 -14
- data/src/test/java/org/embulk/output/elasticsearch/ElasticsearchTestUtils.java +17 -44
- data/src/test/java/org/embulk/output/elasticsearch/TestElasticsearchHttpClient.java +29 -36
- data/src/test/java/org/embulk/output/elasticsearch/TestElasticsearchOutputPlugin.java +16 -19
- metadata +18 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fee5ac83d6cdd1dd3d0f65f6b95e716f8b38389c
|
4
|
+
data.tar.gz: 67fc3c6af37486baa0f7dcbf05b189070d9d9e52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e6bfc587cbaa9d535b78da022d7575e442a5619462ccca2833afa13b0a67a49a76acf94ae16693f38e5fe9f652d343c28eef489d06606b173fab2722f9926e1
|
7
|
+
data.tar.gz: 045a4f6338dbb233b6402021b1998fd4a4801d82f05bd4150ad1a5a121636b7c7a9b33ab23d1ab396247ea0e8331180036bfbb2e8ea95165493789ca511add3c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 0.4.4 - 2017-06-16
|
2
|
+
|
3
|
+
* [maintenance] Improve retry logic - Create RetryHelper instance only at sendRequest() method [#41](https://github.com/muga/embulk-output-elasticsearch/pull/41)
|
4
|
+
|
1
5
|
## 0.4.3 - 2017-06-12
|
2
6
|
|
3
7
|
* [maintenance] Improve exception handling [#38](https://github.com/muga/embulk-output-elasticsearch/pull/38)
|
data/build.gradle
CHANGED
@@ -18,7 +18,7 @@ configurations {
|
|
18
18
|
provided
|
19
19
|
}
|
20
20
|
|
21
|
-
version = "0.4.
|
21
|
+
version = "0.4.4"
|
22
22
|
|
23
23
|
compileJava.options.encoding = 'UTF-8' // source encoding
|
24
24
|
sourceCompatibility = 1.7
|
@@ -27,8 +27,8 @@ targetCompatibility = 1.7
|
|
27
27
|
dependencies {
|
28
28
|
compile "org.embulk:embulk-core:0.8.16"
|
29
29
|
provided "org.embulk:embulk-core:0.8.16"
|
30
|
-
compile "org.embulk.base.restclient:embulk-base-restclient:0.5.
|
31
|
-
compile "org.embulk.base.restclient:embulk-util-retryhelper-jetty92:0.5.
|
30
|
+
compile "org.embulk.base.restclient:embulk-base-restclient:0.5.3"
|
31
|
+
compile "org.embulk.base.restclient:embulk-util-retryhelper-jetty92:0.5.3"
|
32
32
|
|
33
33
|
testCompile "junit:junit:4.+"
|
34
34
|
testCompile "org.embulk:embulk-core:0.8.16:tests"
|
@@ -4,9 +4,10 @@ import com.fasterxml.jackson.core.JsonProcessingException;
|
|
4
4
|
import com.fasterxml.jackson.databind.JsonNode;
|
5
5
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
6
6
|
import com.google.common.annotations.VisibleForTesting;
|
7
|
-
import
|
7
|
+
import com.google.common.base.Throwables;
|
8
8
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
9
9
|
import org.eclipse.jetty.http.HttpMethod;
|
10
|
+
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
10
11
|
import org.embulk.config.ConfigException;
|
11
12
|
import org.embulk.config.UserDataException;
|
12
13
|
import org.embulk.output.elasticsearch.ElasticsearchOutputPluginDelegate.AuthMethod;
|
@@ -15,6 +16,7 @@ import org.embulk.output.elasticsearch.ElasticsearchOutputPluginDelegate.PluginT
|
|
15
16
|
import org.embulk.spi.DataException;
|
16
17
|
import org.embulk.spi.Exec;
|
17
18
|
import org.embulk.spi.time.Timestamp;
|
19
|
+
import org.embulk.util.retryhelper.jetty92.Jetty92ClientCreator;
|
18
20
|
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
19
21
|
import org.embulk.util.retryhelper.jetty92.Jetty92SingleRequester;
|
20
22
|
import org.embulk.util.retryhelper.jetty92.StringJetty92ResponseEntityReader;
|
@@ -54,7 +56,7 @@ public class ElasticsearchHttpClient
|
|
54
56
|
this.log = Exec.getLogger(getClass());
|
55
57
|
}
|
56
58
|
|
57
|
-
public void push(JsonNode records, PluginTask task
|
59
|
+
public void push(JsonNode records, PluginTask task)
|
58
60
|
{
|
59
61
|
int bulkActions = task.getBulkActions();
|
60
62
|
long bulkSize = task.getBulkSize();
|
@@ -78,7 +80,7 @@ public class ElasticsearchHttpClient
|
|
78
80
|
.append(requestString)
|
79
81
|
.append("\n");
|
80
82
|
}
|
81
|
-
sendRequest(path, HttpMethod.POST, task,
|
83
|
+
sendRequest(path, HttpMethod.POST, task, sb.toString());
|
82
84
|
}
|
83
85
|
}
|
84
86
|
catch (JsonProcessingException ex) {
|
@@ -86,14 +88,14 @@ public class ElasticsearchHttpClient
|
|
86
88
|
}
|
87
89
|
}
|
88
90
|
|
89
|
-
public List<String> getIndexByAlias(String aliasName, PluginTask task
|
91
|
+
public List<String> getIndexByAlias(String aliasName, PluginTask task)
|
90
92
|
{
|
91
93
|
// curl -XGET localhost:9200/_alias/{alias}
|
92
94
|
// No alias: 404
|
93
95
|
// Alias found: {"embulk_20161018-183738":{"aliases":{"embulk":{}}}}
|
94
96
|
List<String> indices = new ArrayList<>();
|
95
97
|
String path = String.format("/_alias/%s", aliasName);
|
96
|
-
JsonNode response = sendRequest(path, HttpMethod.GET, task
|
98
|
+
JsonNode response = sendRequest(path, HttpMethod.GET, task);
|
97
99
|
|
98
100
|
Iterator it = response.fieldNames();
|
99
101
|
while (it.hasNext()) {
|
@@ -103,13 +105,13 @@ public class ElasticsearchHttpClient
|
|
103
105
|
return indices;
|
104
106
|
}
|
105
107
|
|
106
|
-
public boolean isIndexExisting(String indexName, PluginTask task
|
108
|
+
public boolean isIndexExisting(String indexName, PluginTask task)
|
107
109
|
{
|
108
110
|
// curl -XGET localhost:9200/{index}
|
109
111
|
// No index: 404
|
110
112
|
// Index found: 200
|
111
113
|
try {
|
112
|
-
sendRequest(indexName, HttpMethod.GET, task
|
114
|
+
sendRequest(indexName, HttpMethod.GET, task);
|
113
115
|
return true;
|
114
116
|
}
|
115
117
|
catch (ResourceNotFoundException ex) {
|
@@ -123,12 +125,12 @@ public class ElasticsearchHttpClient
|
|
123
125
|
return indexName + new SimpleDateFormat("_yyyyMMdd-HHmmss").format(time.toEpochMilli());
|
124
126
|
}
|
125
127
|
|
126
|
-
public boolean isAliasExisting(String aliasName, PluginTask task
|
128
|
+
public boolean isAliasExisting(String aliasName, PluginTask task)
|
127
129
|
{
|
128
130
|
// curl -XGET localhost:9200/_aliases // List all aliases
|
129
131
|
// No aliases: {}
|
130
132
|
// Aliases found: {"embulk_20161018-183738":{"aliases":{"embulk":{}}}}
|
131
|
-
JsonNode response = sendRequest("/_aliases", HttpMethod.GET, task
|
133
|
+
JsonNode response = sendRequest("/_aliases", HttpMethod.GET, task);
|
132
134
|
if (response.size() == 0) {
|
133
135
|
return false;
|
134
136
|
}
|
@@ -143,24 +145,24 @@ public class ElasticsearchHttpClient
|
|
143
145
|
// Should be called just once while Embulk transaction.
|
144
146
|
// Be sure to call after all exporting tasks completed
|
145
147
|
// This method will delete existing index
|
146
|
-
public void reassignAlias(String aliasName, String newIndexName, PluginTask task
|
148
|
+
public void reassignAlias(String aliasName, String newIndexName, PluginTask task)
|
147
149
|
{
|
148
|
-
if (!isAliasExisting(aliasName, task
|
149
|
-
assignAlias(newIndexName, aliasName, task
|
150
|
+
if (!isAliasExisting(aliasName, task)) {
|
151
|
+
assignAlias(newIndexName, aliasName, task);
|
150
152
|
}
|
151
153
|
else {
|
152
|
-
List<String> oldIndices = getIndexByAlias(aliasName, task
|
153
|
-
assignAlias(newIndexName, aliasName, task
|
154
|
+
List<String> oldIndices = getIndexByAlias(aliasName, task);
|
155
|
+
assignAlias(newIndexName, aliasName, task);
|
154
156
|
for (String index : oldIndices) {
|
155
|
-
deleteIndex(index, task
|
157
|
+
deleteIndex(index, task);
|
156
158
|
}
|
157
159
|
}
|
158
160
|
}
|
159
161
|
|
160
|
-
public String getEsVersion(PluginTask task
|
162
|
+
public String getEsVersion(PluginTask task)
|
161
163
|
{
|
162
164
|
// curl -XGET 'http://localhost:9200’
|
163
|
-
JsonNode response = sendRequest("", HttpMethod.GET, task
|
165
|
+
JsonNode response = sendRequest("", HttpMethod.GET, task);
|
164
166
|
return response.get("version").get("number").asText();
|
165
167
|
}
|
166
168
|
|
@@ -208,18 +210,18 @@ public class ElasticsearchHttpClient
|
|
208
210
|
}
|
209
211
|
}
|
210
212
|
|
211
|
-
private void assignAlias(String indexName, String aliasName, PluginTask task
|
213
|
+
private void assignAlias(String indexName, String aliasName, PluginTask task)
|
212
214
|
{
|
213
215
|
try {
|
214
|
-
if (isIndexExisting(indexName, task
|
215
|
-
if (isAliasExisting(aliasName, task
|
216
|
+
if (isIndexExisting(indexName, task)) {
|
217
|
+
if (isAliasExisting(aliasName, task)) {
|
216
218
|
// curl -XPUT http://localhost:9200/_alias -d\
|
217
219
|
// "actions" : [
|
218
220
|
// {"remove" : {"alias" : "{alias}", "index" : "{index_old}"}},
|
219
221
|
// {"add" : {"alias": "{alias}", "index": "{index_new}"}}
|
220
222
|
// ]
|
221
223
|
// Success: {"acknowledged":true}
|
222
|
-
List<String> oldIndices = getIndexByAlias(aliasName, task
|
224
|
+
List<String> oldIndices = getIndexByAlias(aliasName, task);
|
223
225
|
|
224
226
|
Map<String, String> newAlias = new HashMap<>();
|
225
227
|
newAlias.put("alias", aliasName);
|
@@ -243,14 +245,14 @@ public class ElasticsearchHttpClient
|
|
243
245
|
rootTree.put("actions", actions);
|
244
246
|
|
245
247
|
String content = jsonMapper.writeValueAsString(rootTree);
|
246
|
-
sendRequest("/_aliases", HttpMethod.POST, task,
|
248
|
+
sendRequest("/_aliases", HttpMethod.POST, task, content);
|
247
249
|
log.info("Reassigned alias [{}] to index[{}]", aliasName, indexName);
|
248
250
|
}
|
249
251
|
else {
|
250
252
|
// curl -XPUT http://localhost:9200/{index}/_alias/{alias}
|
251
253
|
// Success: {"acknowledged":true}
|
252
254
|
String path = String.format("/%s/_alias/%s", indexName, aliasName);
|
253
|
-
sendRequest(path, HttpMethod.PUT, task
|
255
|
+
sendRequest(path, HttpMethod.PUT, task);
|
254
256
|
log.info("Assigned alias [{}] to Index [{}]", aliasName, indexName);
|
255
257
|
}
|
256
258
|
}
|
@@ -260,24 +262,24 @@ public class ElasticsearchHttpClient
|
|
260
262
|
}
|
261
263
|
}
|
262
264
|
|
263
|
-
private void deleteIndex(String indexName, PluginTask task
|
265
|
+
private void deleteIndex(String indexName, PluginTask task)
|
264
266
|
{
|
265
267
|
// curl -XDELETE localhost:9200/{index}
|
266
268
|
// Success: {"acknowledged":true}
|
267
|
-
if (isIndexExisting(indexName, task
|
268
|
-
waitSnapshot(task
|
269
|
-
sendRequest(indexName, HttpMethod.DELETE, task
|
269
|
+
if (isIndexExisting(indexName, task)) {
|
270
|
+
waitSnapshot(task);
|
271
|
+
sendRequest(indexName, HttpMethod.DELETE, task);
|
270
272
|
log.info("Deleted Index [{}]", indexName);
|
271
273
|
}
|
272
274
|
}
|
273
275
|
|
274
|
-
private void waitSnapshot(PluginTask task
|
276
|
+
private void waitSnapshot(PluginTask task)
|
275
277
|
{
|
276
278
|
int maxSnapshotWaitingMills = task.getMaxSnapshotWaitingSecs() * 1000;
|
277
279
|
long execCount = 1;
|
278
280
|
long totalWaitingTime = 0;
|
279
281
|
// Since only needs exponential backoff, don't need exception handling and others, I don't use Embulk RetryExecutor
|
280
|
-
while (isSnapshotProgressing(task
|
282
|
+
while (isSnapshotProgressing(task)) {
|
281
283
|
long sleepTime = ((long) Math.pow(2, execCount) * 1000);
|
282
284
|
try {
|
283
285
|
Thread.sleep(sleepTime);
|
@@ -296,65 +298,67 @@ public class ElasticsearchHttpClient
|
|
296
298
|
}
|
297
299
|
}
|
298
300
|
|
299
|
-
private boolean isSnapshotProgressing(PluginTask task
|
301
|
+
private boolean isSnapshotProgressing(PluginTask task)
|
300
302
|
{
|
301
303
|
// https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-snapshots.html#_snapshot_status
|
302
304
|
// curl -XGET localhost:9200/_snapshot/_status
|
303
|
-
JsonNode response = sendRequest("/_snapshot/_status", HttpMethod.GET, task
|
305
|
+
JsonNode response = sendRequest("/_snapshot/_status", HttpMethod.GET, task);
|
304
306
|
String snapshots = response.get("snapshots").asText();
|
305
307
|
return !snapshots.equals("");
|
306
308
|
}
|
307
309
|
|
308
|
-
private JsonNode sendRequest(String path, final HttpMethod method, PluginTask task
|
310
|
+
private JsonNode sendRequest(String path, final HttpMethod method, PluginTask task)
|
309
311
|
{
|
310
|
-
return sendRequest(path, method, task,
|
312
|
+
return sendRequest(path, method, task, "");
|
311
313
|
}
|
312
314
|
|
313
|
-
private JsonNode sendRequest(String path, final HttpMethod method, final PluginTask task,
|
315
|
+
private JsonNode sendRequest(String path, final HttpMethod method, final PluginTask task, final String content)
|
314
316
|
{
|
315
317
|
final String uri = createRequestUri(task, path);
|
316
318
|
final String authorizationHeader = getAuthorizationHeader(task);
|
317
319
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
320
|
+
try (Jetty92RetryHelper retryHelper = createRetryHelper(task)) {
|
321
|
+
String responseBody = retryHelper.requestWithRetry(
|
322
|
+
new StringJetty92ResponseEntityReader(task.getTimeoutMills()),
|
323
|
+
new Jetty92SingleRequester() {
|
324
|
+
@Override
|
325
|
+
public void requestOnce(org.eclipse.jetty.client.HttpClient client, org.eclipse.jetty.client.api.Response.Listener responseListener)
|
326
|
+
{
|
327
|
+
org.eclipse.jetty.client.api.Request request = client
|
328
|
+
.newRequest(uri)
|
329
|
+
.accept("application/json")
|
330
|
+
.method(method);
|
331
|
+
if (method == HttpMethod.POST) {
|
332
|
+
request.content(new StringContentProvider(content), "application/json");
|
333
|
+
}
|
334
|
+
|
335
|
+
if (!authorizationHeader.isEmpty()) {
|
336
|
+
request.header("Authorization", authorizationHeader);
|
337
|
+
}
|
338
|
+
request.send(responseListener);
|
330
339
|
}
|
331
340
|
|
332
|
-
|
333
|
-
|
341
|
+
@Override
|
342
|
+
public boolean isExceptionToRetry(Exception exception)
|
343
|
+
{
|
344
|
+
return task.getId().isPresent();
|
334
345
|
}
|
335
|
-
request.send(responseListener);
|
336
|
-
}
|
337
346
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
throw new ResourceNotFoundException("Requested resource was not found");
|
347
|
+
@Override
|
348
|
+
public boolean isResponseStatusToRetry(org.eclipse.jetty.client.api.Response response)
|
349
|
+
{
|
350
|
+
int status = response.getStatus();
|
351
|
+
if (status == 404) {
|
352
|
+
throw new ResourceNotFoundException("Requested resource was not found");
|
353
|
+
}
|
354
|
+
else if (status == 429) {
|
355
|
+
return true; // Retry if 429.
|
356
|
+
}
|
357
|
+
return status / 100 != 4; // Retry unless 4xx except for 429.
|
350
358
|
}
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
return status / 100 != 4; // Retry unless 4xx except for 429.
|
355
|
-
}
|
356
|
-
});
|
357
|
-
return parseJson(responseBody);
|
359
|
+
});
|
360
|
+
return parseJson(responseBody);
|
361
|
+
}
|
358
362
|
}
|
359
363
|
|
360
364
|
private String createRequestUri(PluginTask task, String path)
|
@@ -387,6 +391,28 @@ public class ElasticsearchHttpClient
|
|
387
391
|
}
|
388
392
|
}
|
389
393
|
|
394
|
+
private Jetty92RetryHelper createRetryHelper(PluginTask task)
|
395
|
+
{
|
396
|
+
return new Jetty92RetryHelper(
|
397
|
+
task.getMaximumRetries(),
|
398
|
+
task.getInitialRetryIntervalMillis(),
|
399
|
+
task.getMaximumRetryIntervalMillis(),
|
400
|
+
new Jetty92ClientCreator() {
|
401
|
+
@Override
|
402
|
+
public org.eclipse.jetty.client.HttpClient createAndStart()
|
403
|
+
{
|
404
|
+
org.eclipse.jetty.client.HttpClient client = new org.eclipse.jetty.client.HttpClient(new SslContextFactory());
|
405
|
+
try {
|
406
|
+
client.start();
|
407
|
+
return client;
|
408
|
+
}
|
409
|
+
catch (Exception e) {
|
410
|
+
throw Throwables.propagate(e);
|
411
|
+
}
|
412
|
+
}
|
413
|
+
});
|
414
|
+
}
|
415
|
+
|
390
416
|
@VisibleForTesting
|
391
417
|
protected String getAuthorizationHeader(PluginTask task)
|
392
418
|
{
|
@@ -2,10 +2,7 @@ package org.embulk.output.elasticsearch;
|
|
2
2
|
|
3
3
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
4
4
|
import com.fasterxml.jackson.annotation.JsonValue;
|
5
|
-
import com.google.common.annotations.VisibleForTesting;
|
6
5
|
import com.google.common.base.Optional;
|
7
|
-
import com.google.common.base.Throwables;
|
8
|
-
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
9
6
|
import org.embulk.base.restclient.RestClientOutputPluginDelegate;
|
10
7
|
import org.embulk.base.restclient.RestClientOutputTaskBase;
|
11
8
|
import org.embulk.base.restclient.jackson.JacksonServiceRequestMapper;
|
@@ -21,8 +18,6 @@ import org.embulk.config.TaskReport;
|
|
21
18
|
import org.embulk.spi.Exec;
|
22
19
|
import org.embulk.spi.Schema;
|
23
20
|
import org.embulk.spi.time.TimestampFormatter;
|
24
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92ClientCreator;
|
25
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
26
21
|
import org.joda.time.DateTimeZone;
|
27
22
|
import org.slf4j.Logger;
|
28
23
|
|
@@ -201,21 +196,19 @@ public class ElasticsearchOutputPluginDelegate
|
|
201
196
|
}
|
202
197
|
}
|
203
198
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
throw new ConfigException(String.format("Invalid alias name [%s], an index exists with the same name as the alias", task.getAlias().orNull()));
|
215
|
-
}
|
199
|
+
log.info(String.format("Connecting to Elasticsearch version:%s", client.getEsVersion(task)));
|
200
|
+
log.info("Executing plugin with '{}' mode.", task.getMode());
|
201
|
+
client.validateIndexOrAliasName(task.getIndex(), "index");
|
202
|
+
client.validateIndexOrAliasName(task.getType(), "index_type");
|
203
|
+
|
204
|
+
if (task.getMode().equals(Mode.REPLACE)) {
|
205
|
+
task.setAlias(Optional.of(task.getIndex()));
|
206
|
+
task.setIndex(client.generateNewIndexName(task.getIndex()));
|
207
|
+
if (client.isIndexExisting(task.getAlias().orNull(), task) && !client.isAliasExisting(task.getAlias().orNull(), task)) {
|
208
|
+
throw new ConfigException(String.format("Invalid alias name [%s], an index exists with the same name as the alias", task.getAlias().orNull()));
|
216
209
|
}
|
217
|
-
log.info(String.format("Inserting data into index[%s]", task.getIndex()));
|
218
210
|
}
|
211
|
+
log.info(String.format("Inserting data into index[%s]", task.getIndex()));
|
219
212
|
|
220
213
|
if (task.getAuthMethod() == AuthMethod.BASIC) {
|
221
214
|
if (!task.getUser().isPresent() || !task.getPassword().isPresent()) {
|
@@ -237,8 +230,7 @@ public class ElasticsearchOutputPluginDelegate
|
|
237
230
|
@Override // Overridden from |RecordBufferBuildable|
|
238
231
|
public RecordBuffer buildRecordBuffer(PluginTask task, Schema schema, int taskIndex)
|
239
232
|
{
|
240
|
-
|
241
|
-
return new ElasticsearchRecordBuffer("records", task, retryHelper);
|
233
|
+
return new ElasticsearchRecordBuffer("records", task);
|
242
234
|
}
|
243
235
|
|
244
236
|
@Override
|
@@ -255,36 +247,11 @@ public class ElasticsearchOutputPluginDelegate
|
|
255
247
|
}
|
256
248
|
|
257
249
|
log.info("Insert completed. {} records", totalInserted);
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
client.reassignAlias(task.getAlias().orNull(), task.getIndex(), task, retryHelper);
|
262
|
-
}
|
250
|
+
// Re assign alias only when repale mode
|
251
|
+
if (task.getMode().equals(Mode.REPLACE)) {
|
252
|
+
client.reassignAlias(task.getAlias().orNull(), task.getIndex(), task);
|
263
253
|
}
|
264
254
|
|
265
255
|
return Exec.newConfigDiff();
|
266
256
|
}
|
267
|
-
|
268
|
-
@VisibleForTesting
|
269
|
-
protected Jetty92RetryHelper createRetryHelper(PluginTask task)
|
270
|
-
{
|
271
|
-
return new Jetty92RetryHelper(
|
272
|
-
task.getMaximumRetries(),
|
273
|
-
task.getInitialRetryIntervalMillis(),
|
274
|
-
task.getMaximumRetryIntervalMillis(),
|
275
|
-
new Jetty92ClientCreator() {
|
276
|
-
@Override
|
277
|
-
public org.eclipse.jetty.client.HttpClient createAndStart()
|
278
|
-
{
|
279
|
-
org.eclipse.jetty.client.HttpClient client = new org.eclipse.jetty.client.HttpClient(new SslContextFactory());
|
280
|
-
try {
|
281
|
-
client.start();
|
282
|
-
return client;
|
283
|
-
}
|
284
|
-
catch (Exception e) {
|
285
|
-
throw Throwables.propagate(e);
|
286
|
-
}
|
287
|
-
}
|
288
|
-
});
|
289
|
-
}
|
290
257
|
}
|
@@ -12,7 +12,6 @@ import org.embulk.base.restclient.record.ServiceRecord;
|
|
12
12
|
import org.embulk.config.TaskReport;
|
13
13
|
import org.embulk.output.elasticsearch.ElasticsearchOutputPluginDelegate.PluginTask;
|
14
14
|
import org.embulk.spi.Exec;
|
15
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
16
15
|
import org.slf4j.Logger;
|
17
16
|
|
18
17
|
import java.io.IOException;
|
@@ -28,7 +27,6 @@ public class ElasticsearchRecordBuffer
|
|
28
27
|
private final long bulkActions;
|
29
28
|
private final long bulkSize;
|
30
29
|
private final ElasticsearchHttpClient client;
|
31
|
-
private final Jetty92RetryHelper retryHelper;
|
32
30
|
private final ObjectMapper mapper;
|
33
31
|
private final Logger log;
|
34
32
|
private long totalCount;
|
@@ -36,14 +34,13 @@ public class ElasticsearchRecordBuffer
|
|
36
34
|
private long requestBytes;
|
37
35
|
private ArrayNode records;
|
38
36
|
|
39
|
-
public ElasticsearchRecordBuffer(String attributeName, PluginTask task
|
37
|
+
public ElasticsearchRecordBuffer(String attributeName, PluginTask task)
|
40
38
|
{
|
41
39
|
this.attributeName = attributeName;
|
42
40
|
this.task = task;
|
43
41
|
this.bulkActions = task.getBulkActions();
|
44
42
|
this.bulkSize = task.getBulkSize();
|
45
43
|
this.client = new ElasticsearchHttpClient();
|
46
|
-
this.retryHelper = retryHelper;
|
47
44
|
this.mapper = new ObjectMapper()
|
48
45
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
49
46
|
.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, false);
|
@@ -68,7 +65,7 @@ public class ElasticsearchRecordBuffer
|
|
68
65
|
|
69
66
|
records.add(record);
|
70
67
|
if (requestCount >= bulkActions || requestBytes >= bulkSize) {
|
71
|
-
client.push(records, task
|
68
|
+
client.push(records, task);
|
72
69
|
if (totalCount % 10000 == 0) {
|
73
70
|
log.info("Inserted {} records", totalCount);
|
74
71
|
}
|
@@ -85,18 +82,23 @@ public class ElasticsearchRecordBuffer
|
|
85
82
|
}
|
86
83
|
}
|
87
84
|
|
85
|
+
@Override
|
86
|
+
public void finish()
|
87
|
+
{
|
88
|
+
}
|
89
|
+
|
90
|
+
@Override
|
91
|
+
public void close()
|
92
|
+
{
|
93
|
+
}
|
94
|
+
|
88
95
|
@Override
|
89
96
|
public TaskReport commitWithTaskReportUpdated(TaskReport taskReport)
|
90
97
|
{
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
log.info("Inserted {} records", records.size());
|
95
|
-
}
|
96
|
-
return Exec.newTaskReport().set("inserted", totalCount);
|
97
|
-
}
|
98
|
-
finally {
|
99
|
-
this.retryHelper.close();
|
98
|
+
if (records.size() > 0) {
|
99
|
+
client.push(records, task);
|
100
|
+
log.info("Inserted {} records", records.size());
|
100
101
|
}
|
102
|
+
return Exec.newTaskReport().set("inserted", totalCount);
|
101
103
|
}
|
102
104
|
}
|
@@ -1,14 +1,10 @@
|
|
1
1
|
package org.embulk.output.elasticsearch;
|
2
2
|
|
3
|
-
import com.google.common.base.Throwables;
|
4
3
|
import com.google.common.collect.ImmutableList;
|
5
4
|
import com.google.common.collect.ImmutableMap;
|
6
|
-
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
7
5
|
import org.embulk.config.ConfigSource;
|
8
6
|
import org.embulk.output.elasticsearch.ElasticsearchOutputPluginDelegate.PluginTask;
|
9
7
|
import org.embulk.spi.Exec;
|
10
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92ClientCreator;
|
11
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
12
8
|
|
13
9
|
import java.lang.reflect.Method;
|
14
10
|
import java.util.Arrays;
|
@@ -61,23 +57,21 @@ public class ElasticsearchTestUtils
|
|
61
57
|
public void prepareBeforeTest(PluginTask task) throws Exception
|
62
58
|
{
|
63
59
|
ElasticsearchHttpClient client = new ElasticsearchHttpClient();
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
deleteIndex.invoke(client, ES_INDEX2, task, retryHelper);
|
80
|
-
}
|
60
|
+
Method deleteIndex = ElasticsearchHttpClient.class.getDeclaredMethod("deleteIndex", String.class, PluginTask.class);
|
61
|
+
deleteIndex.setAccessible(true);
|
62
|
+
|
63
|
+
// Delete alias
|
64
|
+
if (client.isAliasExisting(ES_ALIAS, task)) {
|
65
|
+
deleteIndex.invoke(client, ES_ALIAS, task);
|
66
|
+
}
|
67
|
+
|
68
|
+
// Delete index
|
69
|
+
if (client.isIndexExisting(ES_INDEX, task)) {
|
70
|
+
deleteIndex.invoke(client, ES_INDEX, task);
|
71
|
+
}
|
72
|
+
|
73
|
+
if (client.isIndexExisting(ES_INDEX2, task)) {
|
74
|
+
deleteIndex.invoke(client, ES_INDEX2, task);
|
81
75
|
}
|
82
76
|
}
|
83
77
|
|
@@ -94,7 +88,8 @@ public class ElasticsearchTestUtils
|
|
94
88
|
.set("id", ES_ID)
|
95
89
|
.set("bulk_actions", ES_BULK_ACTIONS)
|
96
90
|
.set("bulk_size", ES_BULK_SIZE)
|
97
|
-
.set("concurrent_requests", ES_CONCURRENT_REQUESTS)
|
91
|
+
.set("concurrent_requests", ES_CONCURRENT_REQUESTS)
|
92
|
+
.set("maximum_retries", 2);
|
98
93
|
}
|
99
94
|
|
100
95
|
public ImmutableMap<String, Object> inputConfig()
|
@@ -134,26 +129,4 @@ public class ElasticsearchTestUtils
|
|
134
129
|
builder.add(ImmutableMap.of("name", "comment", "type", "string"));
|
135
130
|
return builder.build();
|
136
131
|
}
|
137
|
-
|
138
|
-
public Jetty92RetryHelper createRetryHelper()
|
139
|
-
{
|
140
|
-
return new Jetty92RetryHelper(
|
141
|
-
2,
|
142
|
-
1000,
|
143
|
-
32000,
|
144
|
-
new Jetty92ClientCreator() {
|
145
|
-
@Override
|
146
|
-
public org.eclipse.jetty.client.HttpClient createAndStart()
|
147
|
-
{
|
148
|
-
org.eclipse.jetty.client.HttpClient client = new org.eclipse.jetty.client.HttpClient(new SslContextFactory());
|
149
|
-
try {
|
150
|
-
client.start();
|
151
|
-
return client;
|
152
|
-
}
|
153
|
-
catch (Exception e) {
|
154
|
-
throw Throwables.propagate(e);
|
155
|
-
}
|
156
|
-
}
|
157
|
-
});
|
158
|
-
}
|
159
132
|
}
|
@@ -7,7 +7,6 @@ import org.embulk.config.ConfigSource;
|
|
7
7
|
import org.embulk.output.elasticsearch.ElasticsearchOutputPluginDelegate.PluginTask;
|
8
8
|
import org.embulk.spi.Exec;
|
9
9
|
import org.embulk.spi.time.Timestamp;
|
10
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
11
10
|
import org.junit.Before;
|
12
11
|
import org.junit.BeforeClass;
|
13
12
|
import org.junit.Rule;
|
@@ -103,53 +102,47 @@ public class TestElasticsearchHttpClient
|
|
103
102
|
public void testCreateAlias() throws Exception
|
104
103
|
{
|
105
104
|
ElasticsearchHttpClient client = new ElasticsearchHttpClient();
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
assertThat(client.getIndexByAlias(ES_ALIAS, task, retryHelper).toString(), is("[" + ES_INDEX2 + "]"));
|
132
|
-
}
|
105
|
+
PluginTask task = utils.config().loadConfig(PluginTask.class);
|
106
|
+
// delete index
|
107
|
+
Method method = ElasticsearchHttpClient.class.getDeclaredMethod("deleteIndex", String.class, PluginTask.class);
|
108
|
+
method.setAccessible(true);
|
109
|
+
method.invoke(client, "newindex", task);
|
110
|
+
|
111
|
+
// create index
|
112
|
+
Method sendRequest = ElasticsearchHttpClient.class.getDeclaredMethod("sendRequest", String.class, HttpMethod.class, PluginTask.class);
|
113
|
+
sendRequest.setAccessible(true);
|
114
|
+
String path = String.format("/%s/", ES_INDEX);
|
115
|
+
sendRequest.invoke(client, path, HttpMethod.PUT, task);
|
116
|
+
|
117
|
+
path = String.format("/%s/", ES_INDEX2);
|
118
|
+
sendRequest.invoke(client, path, HttpMethod.PUT, task);
|
119
|
+
|
120
|
+
// create alias
|
121
|
+
client.reassignAlias(ES_ALIAS, ES_INDEX, task);
|
122
|
+
|
123
|
+
// check alias
|
124
|
+
assertThat(client.isAliasExisting(ES_ALIAS, task), is(true));
|
125
|
+
assertThat(client.getIndexByAlias(ES_ALIAS, task).toString(), is("[" + ES_INDEX + "]"));
|
126
|
+
|
127
|
+
// reassign index
|
128
|
+
client.reassignAlias(ES_ALIAS, ES_INDEX2, task);
|
129
|
+
assertThat(client.getIndexByAlias(ES_ALIAS, task).toString(), is("[" + ES_INDEX2 + "]"));
|
133
130
|
}
|
134
131
|
|
135
132
|
@Test
|
136
133
|
public void testIsIndexExistingWithNonExistsIndex()
|
137
134
|
{
|
138
135
|
ElasticsearchHttpClient client = new ElasticsearchHttpClient();
|
139
|
-
|
140
|
-
|
141
|
-
assertThat(client.isIndexExisting("non-existing-index", task, retryHelper), is(false));
|
142
|
-
}
|
136
|
+
PluginTask task = utils.config().loadConfig(PluginTask.class);
|
137
|
+
assertThat(client.isIndexExisting("non-existing-index", task), is(false));
|
143
138
|
}
|
144
139
|
|
145
140
|
@Test
|
146
141
|
public void testIsAliasExistingWithNonExistsAlias()
|
147
142
|
{
|
148
143
|
ElasticsearchHttpClient client = new ElasticsearchHttpClient();
|
149
|
-
|
150
|
-
|
151
|
-
assertThat(client.isAliasExisting("non-existing-alias", task, retryHelper), is(false));
|
152
|
-
}
|
144
|
+
PluginTask task = utils.config().loadConfig(PluginTask.class);
|
145
|
+
assertThat(client.isAliasExisting("non-existing-alias", task), is(false));
|
153
146
|
}
|
154
147
|
|
155
148
|
@Test
|
@@ -19,7 +19,6 @@ import org.embulk.spi.Schema;
|
|
19
19
|
import org.embulk.spi.TransactionalPageOutput;
|
20
20
|
import org.embulk.spi.time.Timestamp;
|
21
21
|
import org.embulk.standards.CsvParserPlugin;
|
22
|
-
import org.embulk.util.retryhelper.jetty92.Jetty92RetryHelper;
|
23
22
|
import org.junit.Before;
|
24
23
|
import org.junit.BeforeClass;
|
25
24
|
import org.junit.Rule;
|
@@ -171,24 +170,22 @@ public class TestElasticsearchOutputPlugin
|
|
171
170
|
output.commit();
|
172
171
|
Thread.sleep(1500); // Need to wait until index done
|
173
172
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
assertThat(record.get("comment").asText(), is("embulk"));
|
191
|
-
}
|
173
|
+
ElasticsearchHttpClient client = new ElasticsearchHttpClient();
|
174
|
+
Method sendRequest = ElasticsearchHttpClient.class.getDeclaredMethod("sendRequest", String.class, HttpMethod.class, PluginTask.class, String.class);
|
175
|
+
sendRequest.setAccessible(true);
|
176
|
+
String path = String.format("/%s/%s/_search", ES_INDEX, ES_INDEX_TYPE);
|
177
|
+
String sort = "{\"sort\" : \"id\"}";
|
178
|
+
JsonNode response = (JsonNode) sendRequest.invoke(client, path, HttpMethod.POST, task, sort);
|
179
|
+
assertThat(response.get("hits").get("total").asInt(), is(1));
|
180
|
+
if (response.size() > 0) {
|
181
|
+
JsonNode record = response.get("hits").get("hits").get(0).get("_source");
|
182
|
+
assertThat(record.get("id").asInt(), is(1));
|
183
|
+
assertThat(record.get("account").asInt(), is(32864));
|
184
|
+
assertThat(record.get("time").asText(), is("2015-01-27T19:23:49.000+0000"));
|
185
|
+
assertThat(record.get("purchase").asText(), is("2015-01-27T00:00:00.000+0000"));
|
186
|
+
assertThat(record.get("flg").asBoolean(), is(true));
|
187
|
+
assertThat(record.get("score").asDouble(), is(123.45));
|
188
|
+
assertThat(record.get("comment").asText(), is("embulk"));
|
192
189
|
}
|
193
190
|
}
|
194
191
|
|
metadata
CHANGED
@@ -1,57 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-output-elasticsearch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Muga Nishizawa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-06-
|
11
|
+
date: 2017-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
version_requirements: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
14
|
requirement: !ruby/object:Gem::Requirement
|
21
15
|
requirements:
|
22
16
|
- - '>='
|
23
17
|
- !ruby/object:Gem::Version
|
24
18
|
version: '1.0'
|
19
|
+
name: bundler
|
25
20
|
prerelease: false
|
26
21
|
type: :development
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
22
|
version_requirements: !ruby/object:Gem::Requirement
|
30
23
|
requirements:
|
31
24
|
- - '>='
|
32
25
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
35
29
|
requirements:
|
36
30
|
- - '>='
|
37
31
|
- !ruby/object:Gem::Version
|
38
32
|
version: '10.0'
|
33
|
+
name: rake
|
39
34
|
prerelease: false
|
40
35
|
type: :development
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: test-unit
|
43
36
|
version_requirements: !ruby/object:Gem::Requirement
|
44
37
|
requirements:
|
45
|
-
- -
|
38
|
+
- - '>='
|
46
39
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
48
42
|
requirement: !ruby/object:Gem::Requirement
|
49
43
|
requirements:
|
50
44
|
- - ~>
|
51
45
|
- !ruby/object:Gem::Version
|
52
46
|
version: 3.0.2
|
47
|
+
name: test-unit
|
53
48
|
prerelease: false
|
54
49
|
type: :development
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.2
|
55
55
|
description: Elasticsearch output plugin is an Embulk plugin that loads records to Elasticsearch read by any input plugins. Search the input plugins by "embulk-input" keyword.
|
56
56
|
email:
|
57
57
|
- muga.nishizawa@gmail.com
|
@@ -82,9 +82,9 @@ files:
|
|
82
82
|
- src/test/java/org/embulk/output/elasticsearch/TestElasticsearchHttpClient.java
|
83
83
|
- src/test/java/org/embulk/output/elasticsearch/TestElasticsearchOutputPlugin.java
|
84
84
|
- src/test/resources/sample_01.csv
|
85
|
-
- classpath/embulk-base-restclient-0.5.
|
86
|
-
- classpath/embulk-output-elasticsearch-0.4.
|
87
|
-
- classpath/embulk-util-retryhelper-jetty92-0.5.
|
85
|
+
- classpath/embulk-base-restclient-0.5.3.jar
|
86
|
+
- classpath/embulk-output-elasticsearch-0.4.4.jar
|
87
|
+
- classpath/embulk-util-retryhelper-jetty92-0.5.3.jar
|
88
88
|
- classpath/jetty-client-9.2.14.v20151106.jar
|
89
89
|
- classpath/jetty-http-9.2.14.v20151106.jar
|
90
90
|
- classpath/jetty-io-9.2.14.v20151106.jar
|