embulk-input-sftp 0.1.1 → 0.1.2

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: 66e8dab8cd68fdd0a9844dac72d51eaf070cf93a
4
- data.tar.gz: 9de2db631fa24c526e448a2985003063f05a2ae7
3
+ metadata.gz: 107c7dbf7c423b83b5677db6da16b272c8dccab4
4
+ data.tar.gz: edcada631a85858a63c57b7663aedbdb2ab365f6
5
5
  SHA512:
6
- metadata.gz: 5079bf38ede9c5f4b611831144cdcc307c3b71acc6f2b2e43f3570d67abf21f4ca762dddfc0273b3be6cb7740072beaad0865fd5e4a98360d8206c1c88cfe3b0
7
- data.tar.gz: 538c81c868addc2d141770ab5c88d3d38aa0e9e297214a2a42255e80f4f7de91da7ac646eae6aababe301b611ace77df261e7a43931e98c4d3e76bb0100c9e02
6
+ metadata.gz: d28c5e3ba7db475342b75df902b2f588e3259384138e3b1ee696e6582aa1d9ea1fecf5e2f0955cda3a2e19454b69c1d1d346c53b1153030b6406e0680cf03519
7
+ data.tar.gz: 1e7b0e362480f2e610c87871f49f020458054ea5d114a6ab064dde3bf32cf021e44a1954a1ada5f7057fe85d4e780ceaec9b7c5c0e277af2d4f99b283646f26d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
+ ## 0.1.2 - 2015-03-23
2
+
3
+ * [maintenance] Use RetryExecutor when retrying that is provide by embulk-core [#9](https://github.com/sakama/embulk-input-sftp/pull/9)
4
+
1
5
  ## 0.1.1 - 2015-03-18
2
6
 
3
7
  * [feature] Support last_path_ option [#2](https://github.com/sakama/embulk-input-sftp/pull/2)[#4](https://github.com/sakama/embulk-input-sftp/pull/4)[#7](https://github.com/sakama/embulk-input-sftp/pull/7)
4
8
  * [feature] Support path_match_pattern option [#6](https://github.com/sakama/embulk-input-sftp/pull/6)
5
9
  * [maintenance] Add unit test [#3](https://github.com/sakama/embulk-input-sftp/pull/3)
6
- * [maintenance] Skip retry of file downloading when permission denied error happens [#1](https://github.com/sakama/embulk-input-sftp/pull/1)
10
+ * [maintenance] Skip retry of file downloading when permission denied error happens [#1](https://github.com/sakama/embulk-input-sftp/pull/1)
data/README.md CHANGED
@@ -21,8 +21,6 @@ Reads files stored on remote server using SFTP
21
21
  - **path_prefix**: Prefix of output paths (string, required)
22
22
  - **path_match_pattern**: regexp to match file paths. If a file path doesn't match with this pattern, the file will be skipped (regexp string, optional)
23
23
  - **total_file_count_limit**: maximum number of files to read (integer, optional)
24
- - **file_ext**: Extension of output files (string, required)
25
- - **sequence_format**: Format for sequence part of output files (string, default: `".%03d.%02d"`)
26
24
  - **min_task_size (experimental)**: minimum size of a task. If this is larger than 0, one task includes multiple input files. This is useful if too many number of tasks impacts performance of output or executor plugins badly. (integer, optional)
27
25
 
28
26
  ### Proxy configuration
data/build.gradle CHANGED
@@ -14,7 +14,7 @@ configurations {
14
14
  provided
15
15
  }
16
16
 
17
- version = "0.1.1"
17
+ version = "0.1.2"
18
18
 
19
19
  sourceCompatibility = 1.7
20
20
  targetCompatibility = 1.7
@@ -16,9 +16,13 @@ import org.embulk.spi.Exec;
16
16
  import org.embulk.spi.TransactionalFileInput;
17
17
  import org.embulk.spi.unit.LocalFile;
18
18
  import org.embulk.spi.util.InputStreamFileInput;
19
+ import org.embulk.spi.util.RetryExecutor.RetryGiveupException;
20
+ import org.embulk.spi.util.RetryExecutor.Retryable;
19
21
  import org.slf4j.Logger;
22
+ import static org.embulk.spi.util.RetryExecutor.retryExecutor;
20
23
 
21
24
  import java.io.File;
25
+ import java.io.IOException;
22
26
  import java.net.URI;
23
27
  import java.net.URISyntaxException;
24
28
 
@@ -56,6 +60,7 @@ public class SftpFileInput
56
60
  }
57
61
 
58
62
  StandardFileSystemManager manager = new StandardFileSystemManager();
63
+ manager.setClassLoader(SftpFileInput.class.getClassLoader());
59
64
  try {
60
65
  manager.init();
61
66
  }
@@ -149,64 +154,81 @@ public class SftpFileInput
149
154
  }
150
155
  }
151
156
 
152
- public static FileList listFilesByPrefix(PluginTask task)
157
+ public static FileList listFilesByPrefix(final PluginTask task)
153
158
  {
154
- FileList.Builder builder = new FileList.Builder(task);
159
+ final FileList.Builder builder = new FileList.Builder(task);
155
160
  int maxConnectionRetry = task.getMaxConnectionRetry();
156
- String lastKey = null;
157
161
 
158
- StandardFileSystemManager manager = null;
159
- int count = 0;
160
- while (true) {
161
- try {
162
- manager = initializeStandardFileSystemManager();
163
- FileSystemOptions fsOptions = initializeFsOptions(task);
162
+ try {
163
+ return retryExecutor()
164
+ .withRetryLimit(maxConnectionRetry)
165
+ .withInitialRetryWait(500)
166
+ .withMaxRetryWait(30 * 1000)
167
+ .runInterruptible(new Retryable<FileList>() {
168
+ @Override
169
+ public FileList call() throws IOException
170
+ {
171
+ String lastKey = null;
172
+ log.info("Getting to download file list");
173
+ StandardFileSystemManager manager = initializeStandardFileSystemManager();
174
+ FileSystemOptions fsOptions = initializeFsOptions(task);
164
175
 
165
- if (task.getLastPath().isPresent() && !task.getLastPath().get().isEmpty()) {
166
- lastKey = manager.resolveFile(getSftpFileUri(task, task.getLastPath().get()), fsOptions).toString();
167
- }
176
+ if (task.getLastPath().isPresent() && !task.getLastPath().get().isEmpty()) {
177
+ lastKey = manager.resolveFile(getSftpFileUri(task, task.getLastPath().get()), fsOptions).toString();
178
+ }
168
179
 
169
- FileObject files = manager.resolveFile(getSftpFileUri(task, task.getPathPrefix()), fsOptions);
170
- String basename = FilenameUtils.getBaseName(task.getPathPrefix());
171
- if (files.isFolder()) {
172
- for (FileObject f : files.getChildren()) {
173
- if (f.isFile()) {
174
- addFileToList(builder, f.toString(), f.getContent().getSize(), "", lastKey);
180
+ FileObject files = manager.resolveFile(getSftpFileUri(task, task.getPathPrefix()), fsOptions);
181
+ String basename = FilenameUtils.getBaseName(task.getPathPrefix());
182
+ if (files.isFolder()) {
183
+ for (FileObject f : files.getChildren()) {
184
+ if (f.isFile()) {
185
+ addFileToList(builder, f.toString(), f.getContent().getSize(), "", lastKey);
186
+ }
187
+ }
188
+ }
189
+ else {
190
+ FileObject parent = files.getParent();
191
+ for (FileObject f : parent.getChildren()) {
192
+ if (f.isFile()) {
193
+ addFileToList(builder, f.toString(), f.getContent().getSize(), basename, lastKey);
194
+ }
195
+ }
196
+ }
197
+ return builder.build();
175
198
  }
176
- }
177
- }
178
- else {
179
- FileObject parent = files.getParent();
180
- for (FileObject f : parent.getChildren()) {
181
- if (f.isFile()) {
182
- addFileToList(builder, f.toString(), f.getContent().getSize(), basename, lastKey);
199
+
200
+ @Override
201
+ public boolean isRetryableException(Exception exception)
202
+ {
203
+ return true;
183
204
  }
184
- }
185
- }
186
- return builder.build();
187
- }
188
- catch (FileSystemException ex) {
189
- if (++count == maxConnectionRetry) {
190
- Throwables.propagate(ex);
191
- }
192
- log.warn("failed to connect sftp server: " + ex.getMessage(), ex);
193
205
 
194
- try {
195
- long sleepTime = ((long) Math.pow(2, count) * 1000);
196
- log.warn("sleep in next connection retry: {} milliseconds", sleepTime);
197
- Thread.sleep(sleepTime); // milliseconds
198
- }
199
- catch (InterruptedException ex2) {
200
- // Ignore this exception because this exception is just about `sleep`.
201
- log.warn(ex2.getMessage(), ex2);
202
- }
203
- log.warn("retrying to connect sftp server: " + count + " times");
204
- }
205
- finally {
206
- if (manager != null) {
207
- manager.close();
208
- }
209
- }
206
+ @Override
207
+ public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
208
+ throws RetryGiveupException
209
+ {
210
+ String message = String.format("SFTP GET request failed. Retrying %d/%d after %d seconds. Message: %s",
211
+ retryCount, retryLimit, retryWait / 1000, exception.getMessage());
212
+ if (retryCount % 3 == 0) {
213
+ log.warn(message, exception);
214
+ }
215
+ else {
216
+ log.warn(message);
217
+ }
218
+ }
219
+
220
+ @Override
221
+ public void onGiveup(Exception firstException, Exception lastException)
222
+ throws RetryGiveupException
223
+ {
224
+ }
225
+ });
226
+ }
227
+ catch (RetryGiveupException ex) {
228
+ throw Throwables.propagate(ex.getCause());
229
+ }
230
+ catch (InterruptedException ex) {
231
+ throw Throwables.propagate(ex);
210
232
  }
211
233
  }
212
234
 
@@ -1,15 +1,20 @@
1
1
  package org.embulk.input.sftp;
2
2
 
3
+ import com.google.common.base.Throwables;
3
4
  import org.apache.commons.vfs2.FileObject;
4
5
  import org.apache.commons.vfs2.FileSystemException;
5
6
  import org.apache.commons.vfs2.FileSystemOptions;
6
7
  import org.apache.commons.vfs2.impl.StandardFileSystemManager;
7
8
  import org.embulk.spi.Exec;
8
9
  import org.embulk.spi.util.InputStreamFileInput;
10
+ import org.embulk.spi.util.RetryExecutor.RetryGiveupException;
11
+ import org.embulk.spi.util.RetryExecutor.Retryable;
9
12
  import org.slf4j.Logger;
13
+ import static org.embulk.spi.util.RetryExecutor.retryExecutor;
10
14
 
11
15
  import java.io.IOException;
12
16
  import java.io.InputStream;
17
+ import java.io.InterruptedIOException;
13
18
  import java.util.Iterator;
14
19
 
15
20
  public class SingleFileProvider
@@ -37,33 +42,58 @@ public class SingleFileProvider
37
42
  return null;
38
43
  }
39
44
  opened = true;
40
- String key = iterator.next();
45
+ final String key = iterator.next();
41
46
 
42
- int count = 0;
43
- while (true) {
44
- try {
45
- FileObject file = manager.resolveFile(key, fsOptions);
46
- log.info("Starting to download file {}", key);
47
+ try {
48
+ return retryExecutor()
49
+ .withRetryLimit(maxConnectionRetry)
50
+ .withInitialRetryWait(500)
51
+ .withMaxRetryWait(30 * 1000)
52
+ .runInterruptible(new Retryable<InputStream>() {
53
+ @Override
54
+ public InputStream call() throws FileSystemException
55
+ {
56
+ log.info("Starting to download file {}", key);
57
+ FileObject file = manager.resolveFile(key, fsOptions);
58
+ return file.getContent().getInputStream();
59
+ }
47
60
 
48
- return file.getContent().getInputStream();
49
- }
50
- catch (FileSystemException ex) {
51
- if (++count == maxConnectionRetry || ex.getMessage().indexOf("Permission denied") > 0) {
52
- throw ex;
53
- }
54
- log.warn("failed to connect sftp server: " + ex.getMessage(), ex);
61
+ @Override
62
+ public boolean isRetryableException(Exception exception)
63
+ {
64
+ return true;
65
+ }
55
66
 
56
- try {
57
- long sleepTime = ((long) Math.pow(2, count) * 1000);
58
- log.warn("sleep in next connection retry: {} milliseconds", sleepTime);
59
- Thread.sleep(sleepTime); // milliseconds
60
- }
61
- catch (InterruptedException ex2) {
62
- // Ignore this exception because this exception is just about `sleep`.
63
- log.warn(ex2.getMessage(), ex2);
64
- }
65
- log.warn("retrying to connect sftp server: " + count + " times");
66
- }
67
+ @Override
68
+ public void onRetry(Exception exception, int retryCount, int retryLimit, int retryWait)
69
+ throws RetryGiveupException
70
+ {
71
+ if (exception.getMessage().indexOf("Permission denied") > 0) {
72
+ log.error("Could not download file due to Permission Denied");
73
+ throw new RetryGiveupException(exception);
74
+ }
75
+ String message = String.format("SFTP GET request failed. Retrying %d/%d after %d seconds. Message: %s",
76
+ retryCount, retryLimit, retryWait / 1000, exception.getMessage());
77
+ if (retryCount % 3 == 0) {
78
+ log.warn(message, exception);
79
+ }
80
+ else {
81
+ log.warn(message);
82
+ }
83
+ }
84
+
85
+ @Override
86
+ public void onGiveup(Exception firstException, Exception lastException)
87
+ throws RetryGiveupException
88
+ {
89
+ }
90
+ });
91
+ }
92
+ catch (RetryGiveupException ex) {
93
+ throw Throwables.propagate(ex.getCause());
94
+ }
95
+ catch (InterruptedException ex) {
96
+ throw new InterruptedIOException();
67
97
  }
68
98
  }
69
99
 
@@ -183,8 +183,8 @@ public class TestSftpFileInputPlugin
183
183
  @Test
184
184
  public void testListFiles() throws Exception
185
185
  {
186
- uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv");
187
- uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv");
186
+ uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv", true);
187
+ uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv", true);
188
188
 
189
189
  PluginTask task = config.loadConfig(PluginTask.class);
190
190
 
@@ -215,8 +215,8 @@ public class TestSftpFileInputPlugin
215
215
  @Test
216
216
  public void testSftpInputByOpen() throws Exception
217
217
  {
218
- uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv");
219
- uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv");
218
+ uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv", true);
219
+ uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv", true);
220
220
 
221
221
  PluginTask task = config.loadConfig(PluginTask.class);
222
222
  runner.transaction(config, new Control());
@@ -235,8 +235,8 @@ public class TestSftpFileInputPlugin
235
235
  // try {
236
236
  // proxyServer = createProxyServer(PROXY_PORT);
237
237
  //
238
- // uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv");
239
- // uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv");
238
+ // uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv", true);
239
+ // uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv", true);
240
240
  //
241
241
  // ConfigSource config = Exec.newConfigSource()
242
242
  // .set("host", HOST)
@@ -269,8 +269,8 @@ public class TestSftpFileInputPlugin
269
269
  @Test
270
270
  public void testSftpInputByOpenTimeout() throws Exception
271
271
  {
272
- uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv");
273
- uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv");
272
+ uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv", true);
273
+ uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv", true);
274
274
 
275
275
  ConfigSource config = Exec.newConfigSource()
276
276
  .set("host", HOST)
@@ -289,6 +289,29 @@ public class TestSftpFileInputPlugin
289
289
  runner.transaction(config, new Control());
290
290
  }
291
291
 
292
+ @Test
293
+ public void testSftpInputByOpenFailWithRetry() throws Exception
294
+ {
295
+ uploadFile(Resources.getResource("sample_01.csv").getPath(), REMOTE_DIRECTORY + "sample_01.csv", false);
296
+ uploadFile(Resources.getResource("sample_02.csv").getPath(), REMOTE_DIRECTORY + "sample_02.csv", false);
297
+
298
+ ConfigSource config = Exec.newConfigSource()
299
+ .set("host", HOST)
300
+ .set("port", PORT)
301
+ .set("user", USERNAME)
302
+ .set("password", PASSWORD)
303
+ .set("path_prefix", REMOTE_DIRECTORY)
304
+ .set("max_connection_retry", 2)
305
+ .set("last_path", "")
306
+ .set("parser", parserConfig(schemaConfig()));
307
+
308
+ exception.expect(RuntimeException.class);
309
+ exception.expectCause(CoreMatchers.<Throwable>instanceOf(FileSystemException.class));
310
+ exception.expectMessage(CoreMatchers.containsString("Unknown message with code \"java.nio.file.AccessDeniedException"));
311
+
312
+ runner.transaction(config, new Control());
313
+ }
314
+
292
315
  @Test
293
316
  public void testProxyType()
294
317
  {
@@ -377,7 +400,7 @@ public class TestSftpFileInputPlugin
377
400
  .start();
378
401
  }
379
402
 
380
- private void uploadFile(String localPath, String remotePath) throws Exception
403
+ private void uploadFile(String localPath, String remotePath, boolean isReadable) throws Exception
381
404
  {
382
405
  PluginTask task = config.loadConfig(PluginTask.class);
383
406
 
@@ -388,11 +411,15 @@ public class TestSftpFileInputPlugin
388
411
  while (true) {
389
412
  try {
390
413
  StandardFileSystemManager manager = new StandardFileSystemManager();
414
+ manager.setClassLoader(TestSftpFileInputPlugin.class.getClassLoader());
391
415
  manager.init();
392
416
 
393
417
  FileObject localFile = manager.resolveFile(localPath);
394
418
  FileObject remoteFile = manager.resolveFile(uri, fsOptions);
395
419
  remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
420
+ if (!isReadable) {
421
+ remoteFile.setReadable(false, false);
422
+ }
396
423
 
397
424
  if (log.isDebugEnabled()) {
398
425
  FileObject files = manager.resolveFile(SftpFileInput.getSftpFileUri(task, REMOTE_DIRECTORY));
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-input-sftp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
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-18 00:00:00.000000000 Z
11
+ date: 2016-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -71,7 +71,7 @@ files:
71
71
  - classpath/commons-io-1.3.2.jar
72
72
  - classpath/commons-logging-1.2.jar
73
73
  - classpath/commons-vfs2-2.1.1660580.2.jar
74
- - classpath/embulk-input-sftp-0.1.1.jar
74
+ - classpath/embulk-input-sftp-0.1.2.jar
75
75
  - classpath/jsch-0.1.53.jar
76
76
  homepage: https://github.com/sakama/embulk-input-sftp
77
77
  licenses: