embulk-input-azure_blob_storage 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 49b71df05579f8c392ec70089aaeca95f1b81144
4
- data.tar.gz: a63ffb1663b9bbed5827211dbb62eeb04b20a987
3
+ metadata.gz: 60cc4b85fafbfd719fdb70232f8c7b44c3153d9f
4
+ data.tar.gz: 50af2362a8edbc752bbc1116a36ede8a3f64aa84
5
5
  SHA512:
6
- metadata.gz: 1a43a45c850746c1a50b9f12be823f0081ea9deddd4403e831f2533e6af4ab4861405e45cc62824fcb637b6509178fceeb6cad4f583542677e0ee3383beb8e43
7
- data.tar.gz: d5e6066c047f60034d50ff6084919157476f962adf5c9f2b1a59685a97d83a254637ed0037276629714e2b1223c229c0564b58c162cfffbb58b10a4822f563aa
6
+ metadata.gz: b11039548309b1d49bc7b87e54a6ff60eb36863e8f75127f087f71520a957d833aac197f577dbbf262ae0d68a656edd92b0c5fa5ed42fb7c90c62f8e5f551b15
7
+ data.tar.gz: ecb4b533a64440f78a07ebdb8e1a7b5a4dba91a79a4c7121e32463ecdb4e5746d26186078ae938dd73774273001d917ac09b914d20fa312690ccde91a49986d5
@@ -1,3 +1,7 @@
1
+ ## 0.1.5 - 2015-03-30
2
+
3
+ * [maintenance] Use RetryExecutor when retry is needed [#8](https://github.com/sakama/embulk-input-azure_blob_storage/pull/8)
4
+
1
5
  ## 0.1.4 - 2015-03-22
2
6
 
3
7
  * [new feature] Support `last_path` option [#7](https://github.com/sakama/embulk-input-azure_blob_storage/pull/7)
@@ -15,4 +19,4 @@
15
19
  ## 0.1.1 - 2015-10-11
16
20
 
17
21
  * [maintenance] Change 'DefaultEndpointsProtocol' from http to https [#1](https://github.com/sakama/embulk-input-azure_blob_storage/pull/1)
18
- * [maintenance] Specify targetCompatibility = 1.7
22
+ * [maintenance] Specify targetCompatibility = 1.7
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Azure blob Storage file input plugin for Embulk
1
+ # Azure Blob Storage file input plugin for Embulk
2
2
 
3
- [Embulk](http://www.embulk.org/) file input plugin read files stored on [Microsoft Azure](https://azure.microsoft.com/) [blob Storage](https://azure.microsoft.com/en-us/documentation/articles/storage-introduction/#blob-storage)
3
+ [Embulk](http://www.embulk.org/) file input plugin read files stored on [Microsoft Azure](https://azure.microsoft.com/) [Blob Storage](https://azure.microsoft.com/en-us/documentation/articles/storage-introduction/#blob-storage)
4
4
 
5
5
  ## Overview
6
6
 
@@ -129,4 +129,4 @@ $ launchctl load ~/Library/LaunchAgents/environment.plist
129
129
  $ launchctl getenv AZURE_ACCOUNT_NAME //try to get value.
130
130
 
131
131
  Then start your applications.
132
- ```
132
+ ```
@@ -17,7 +17,7 @@ configurations {
17
17
  sourceCompatibility = 1.7
18
18
  targetCompatibility = 1.7
19
19
 
20
- version = "0.1.4"
20
+ version = "0.1.5"
21
21
 
22
22
  dependencies {
23
23
  compile "org.embulk:embulk-core:0.8.2"
@@ -65,8 +65,8 @@ Gem::Specification.new do |spec|
65
65
  spec.name = "${project.name}"
66
66
  spec.version = "${project.version}"
67
67
  spec.authors = ["Satoshi Akama"]
68
- spec.summary = %[Microsoft Azure blob Storage file input plugin for Embulk]
69
- spec.description = %[Reads files stored on Microsoft Azure blob Storage.]
68
+ spec.summary = %[Microsoft Azure Blob Storage file input plugin for Embulk]
69
+ spec.description = %[Reads files stored on Microsoft Azure Blob Storage.]
70
70
  spec.email = ["satoshiakama@gmail.com"]
71
71
  spec.licenses = ["Apache-2.0"]
72
72
  spec.homepage = "https://github.com/sakama/embulk-input-azure_blob_storage"
@@ -27,7 +27,10 @@ import org.embulk.spi.Exec;
27
27
  import org.embulk.spi.FileInputPlugin;
28
28
  import org.embulk.spi.TransactionalFileInput;
29
29
  import org.embulk.spi.util.InputStreamFileInput;
30
+ import org.embulk.spi.util.RetryExecutor.RetryGiveupException;
31
+ import org.embulk.spi.util.RetryExecutor.Retryable;
30
32
  import org.slf4j.Logger;
33
+ import static org.embulk.spi.util.RetryExecutor.retryExecutor;
31
34
 
32
35
  import java.io.IOException;
33
36
  import java.io.InputStream;
@@ -63,7 +66,7 @@ public class AzureBlobStorageFileInputPlugin
63
66
  int getMaxResults();
64
67
 
65
68
  @Config("max_connection_retry")
66
- @ConfigDefault("5") // 5 times retry to connect sftp server if failed.
69
+ @ConfigDefault("10") // 10 times retry to connect sftp server if failed.
67
70
  int getMaxConnectionRetry();
68
71
 
69
72
  FileList getFiles();
@@ -126,44 +129,85 @@ public class AzureBlobStorageFileInputPlugin
126
129
  }
127
130
  FileList.Builder builder = new FileList.Builder(task);
128
131
 
129
- return listFilesWithPrefix(builder, client, task.getContainer(), task.getPathPrefix(), task.getLastPath(), task.getMaxResults());
132
+ return listFilesWithPrefix(builder, client, task.getContainer(), task.getPathPrefix(),
133
+ task.getLastPath(), task.getMaxResults(), task.getMaxConnectionRetry());
130
134
  }
131
135
 
132
- private static FileList listFilesWithPrefix(FileList.Builder builder, CloudBlobClient client, String containerName,
133
- String prefix, Optional<String> lastPath, int maxResults)
136
+ private static FileList listFilesWithPrefix(final FileList.Builder builder, final CloudBlobClient client,
137
+ final String containerName, final String prefix, final Optional<String> lastPath,
138
+ final int maxResults, final int maxConnectionRetry)
134
139
  {
135
- String lastKey = (lastPath.isPresent() && !lastPath.get().isEmpty()) ? createNextToken(lastPath.get()) : null;
136
- ResultContinuation token = null;
137
- if (lastKey != null) {
138
- token = new ResultContinuation();
139
- token.setContinuationType(ResultContinuationType.BLOB);
140
- log.debug("lastPath: {}", lastPath.get());
141
- log.debug("lastPath(Base64encoded): {}", lastKey);
142
- token.setNextMarker(lastKey);
143
- }
144
-
140
+ final String lastKey = (lastPath.isPresent() && !lastPath.get().isEmpty()) ? createNextToken(lastPath.get()) : null;
145
141
  try {
146
- CloudBlobContainer container = client.getContainerReference(containerName);
147
- ResultSegment<ListBlobItem> blobs;
148
- do {
149
- blobs = container.listBlobsSegmented(prefix, true, null, maxResults, token, null, null);
150
- log.debug(String.format("result count(include directory):%s continuationToken:%s", blobs.getLength(), blobs.getContinuationToken()));
151
- for (ListBlobItem blobItem : blobs.getResults()) {
152
- if (blobItem instanceof CloudBlob) {
153
- CloudBlob blob = (CloudBlob) blobItem;
154
- if (blob.exists() && !blob.getUri().toString().endsWith("/")) {
155
- builder.add(blob.getName(), blob.getProperties().getLength());
156
- log.debug(String.format("name:%s, class:%s, uri:%s", blob.getName(), blob.getClass(), blob.getUri()));
142
+ return retryExecutor()
143
+ .withRetryLimit(maxConnectionRetry)
144
+ .withInitialRetryWait(500)
145
+ .withMaxRetryWait(30 * 1000)
146
+ .runInterruptible(new Retryable<FileList>() {
147
+ @Override
148
+ public FileList call() throws StorageException, URISyntaxException, IOException
149
+ {
150
+ ResultContinuation token = null;
151
+ if (lastKey != null) {
152
+ token = new ResultContinuation();
153
+ token.setContinuationType(ResultContinuationType.BLOB);
154
+ log.debug("lastPath: {}", lastPath.get());
155
+ log.debug("lastPath(Base64encoded): {}", lastKey);
156
+ token.setNextMarker(lastKey);
157
+ }
158
+
159
+ CloudBlobContainer container = client.getContainerReference(containerName);
160
+ ResultSegment<ListBlobItem> blobs;
161
+ do {
162
+ blobs = container.listBlobsSegmented(prefix, true, null, maxResults, token, null, null);
163
+ log.debug(String.format("result count(include directory):%s continuationToken:%s", blobs.getLength(), blobs.getContinuationToken()));
164
+ for (ListBlobItem blobItem : blobs.getResults()) {
165
+ if (blobItem instanceof CloudBlob) {
166
+ CloudBlob blob = (CloudBlob) blobItem;
167
+ if (blob.exists() && !blob.getUri().toString().endsWith("/")) {
168
+ builder.add(blob.getName(), blob.getProperties().getLength());
169
+ log.debug(String.format("name:%s, class:%s, uri:%s", blob.getName(), blob.getClass(), blob.getUri()));
170
+ }
171
+ }
172
+ }
173
+ token = blobs.getContinuationToken();
174
+ } while (blobs.getContinuationToken() != null);
175
+ return builder.build();
176
+ }
177
+
178
+ @Override
179
+ public boolean isRetryableException(Exception exception)
180
+ {
181
+ return true;
182
+ }
183
+
184
+ @Override
185
+ public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
186
+ throws RetryGiveupException
187
+ {
188
+ String message = String.format("SFTP GET request failed. Retrying %d/%d after %d seconds. Message: %s",
189
+ retryCount, retryLimit, retryWait / 1000, exception.getMessage());
190
+ if (retryCount % 3 == 0) {
191
+ log.warn(message, exception);
192
+ }
193
+ else {
194
+ log.warn(message);
195
+ }
157
196
  }
158
- }
159
- }
160
- token = blobs.getContinuationToken();
161
- } while (blobs.getContinuationToken() != null);
197
+
198
+ @Override
199
+ public void onGiveup(Exception firstException, Exception lastException)
200
+ throws RetryGiveupException
201
+ {
202
+ }
203
+ });
204
+ }
205
+ catch (RetryGiveupException ex) {
206
+ throw Throwables.propagate(ex.getCause());
162
207
  }
163
- catch (URISyntaxException | StorageException ex) {
208
+ catch (InterruptedException ex) {
164
209
  throw Throwables.propagate(ex);
165
210
  }
166
- return builder.build();
167
211
  }
168
212
 
169
213
  @Override
@@ -215,31 +259,54 @@ public class AzureBlobStorageFileInputPlugin
215
259
  if (opened || !iterator.hasNext()) {
216
260
  return null;
217
261
  }
262
+ final String key = iterator.next();
218
263
  opened = true;
219
- int count = 0;
220
-
221
- while (true) {
222
- try {
223
- CloudBlobContainer container = client.getContainerReference(containerName);
224
- CloudBlob blob = container.getBlockBlobReference(iterator.next());
225
- return blob.openInputStream();
226
- }
227
- catch (StorageException | URISyntaxException ex) {
228
- if (++count == maxConnectionRetry) {
229
- Throwables.propagate(ex);
230
- }
231
-
232
- try {
233
- long sleepTime = ((long) Math.pow(2, count) * 1000);
234
- log.warn("Sleep in next connection retry: {} milliseconds", sleepTime);
235
- Thread.sleep(sleepTime);
236
- }
237
- catch (InterruptedException ex2) {
238
- // Ignore this exception because this exception is just about `sleep`.
239
- log.warn(ex2.getMessage(), ex2);
240
- }
241
- log.warn("Retrying to connect Azure server: " + count + " times");
242
- }
264
+ try {
265
+ return retryExecutor()
266
+ .withRetryLimit(maxConnectionRetry)
267
+ .withInitialRetryWait(500)
268
+ .withMaxRetryWait(30 * 1000)
269
+ .runInterruptible(new Retryable<InputStream>() {
270
+ @Override
271
+ public InputStream call() throws StorageException, URISyntaxException, IOException
272
+ {
273
+ CloudBlobContainer container = client.getContainerReference(containerName);
274
+ CloudBlob blob = container.getBlockBlobReference(key);
275
+ return blob.openInputStream();
276
+ }
277
+
278
+ @Override
279
+ public boolean isRetryableException(Exception exception)
280
+ {
281
+ return true;
282
+ }
283
+
284
+ @Override
285
+ public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
286
+ throws RetryGiveupException
287
+ {
288
+ String message = String.format("Azure Blob Storage GET request failed. Retrying %d/%d after %d seconds. Message: %s",
289
+ retryCount, retryLimit, retryWait / 1000, exception.getMessage());
290
+ if (retryCount % 3 == 0) {
291
+ log.warn(message, exception);
292
+ }
293
+ else {
294
+ log.warn(message);
295
+ }
296
+ }
297
+
298
+ @Override
299
+ public void onGiveup(Exception firstException, Exception lastException)
300
+ throws RetryGiveupException
301
+ {
302
+ }
303
+ });
304
+ }
305
+ catch (RetryGiveupException ex) {
306
+ throw Throwables.propagate(ex.getCause());
307
+ }
308
+ catch (InterruptedException ex) {
309
+ throw Throwables.propagate(ex);
243
310
  }
244
311
  }
245
312
 
@@ -90,7 +90,7 @@ public class TestAzureBlobStorageFileInputPlugin
90
90
 
91
91
  PluginTask task = config.loadConfig(PluginTask.class);
92
92
  assertEquals(5000, task.getMaxResults());
93
- assertEquals(5, task.getMaxConnectionRetry());
93
+ assertEquals(10, task.getMaxConnectionRetry());
94
94
  }
95
95
 
96
96
  @Test(expected = ConfigException.class)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-input-azure_blob_storage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Satoshi Akama
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-22 00:00:00.000000000 Z
11
+ date: 2016-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: Reads files stored on Microsoft Azure blob Storage.
41
+ description: Reads files stored on Microsoft Azure Blob Storage.
42
42
  email:
43
43
  - satoshiakama@gmail.com
44
44
  executables: []
@@ -64,7 +64,7 @@ files:
64
64
  - src/test/resources/sample_02.csv
65
65
  - classpath/azure-storage-4.0.0.jar
66
66
  - classpath/commons-lang3-3.4.jar
67
- - classpath/embulk-input-azure_blob_storage-0.1.4.jar
67
+ - classpath/embulk-input-azure_blob_storage-0.1.5.jar
68
68
  - classpath/jackson-core-2.6.0.jar
69
69
  homepage: https://github.com/sakama/embulk-input-azure_blob_storage
70
70
  licenses:
@@ -89,5 +89,5 @@ rubyforge_project:
89
89
  rubygems_version: 2.1.9
90
90
  signing_key:
91
91
  specification_version: 4
92
- summary: Microsoft Azure blob Storage file input plugin for Embulk
92
+ summary: Microsoft Azure Blob Storage file input plugin for Embulk
93
93
  test_files: []