Skip to content

Commit e5b3296

Browse files
committed
Merge pull request #17 from sonots/retry
Retry
2 parents a353850 + 6a503a9 commit e5b3296

File tree

5 files changed

+123
-31
lines changed

5 files changed

+123
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ build/
88
.idea
99
*.iml
1010
example/config.yml
11+
.vagrant

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,21 @@ out:
103103
```
104104

105105
## Run Example
106-
replace settings in `example/sample.yml` before running.
107106

108107
```
109108
$ ./gradlew classpath
109+
```
110+
111+
Use `vagrant` to start a remote sshd server:
112+
113+
```
114+
$ vagrant up
115+
```
116+
117+
Run:
118+
119+
120+
```
110121
$ embulk run -Ilib example/sample.yml
111122
```
112123

Vagrantfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# -*- mode: ruby -*-
2+
# vi: set ft=ruby :
3+
4+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5+
VAGRANTFILE_API_VERSION = "2"
6+
7+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8+
# All Vagrant configuration is done here. The most common configuration
9+
# options are documented and commented below. For a complete reference,
10+
# please see the online documentation at vagrantup.com.
11+
12+
# Every Vagrant virtual environment requires a box to build off of.
13+
config.vm.box = "centos6.5.3"
14+
config.vm.box_url = 'https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box'
15+
16+
# name
17+
config.vm.define "vagrant-centos"
18+
config.ssh.forward_agent = true
19+
config.vm.network "forwarded_port", guest: 22, host: 2210
20+
end
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ in:
1616
out:
1717
type: sftp
1818
host: 127.0.0.1
19-
port: 22
20-
user: your_name
21-
password: your_password
22-
secret_key_file: your_secret_key_file
23-
secret_key_passphrase: your_secret_key_passphrase
19+
port: 2210
20+
user: vagrant
21+
# password:
22+
secret_key_file: {{ env.PWD }}/.vagrant/machines/vagrant-centos/virtualbox/private_key
23+
# secret_key_passphrase:
2424
user_directory_is_root: true
2525
path_prefix: /tmp/embulk_output_sftp/data
2626
file_ext: .tsv
@@ -36,4 +36,5 @@ out:
3636
quote: "\""
3737
escape: "\\"
3838
null_string: ""
39-
default_timezone: 'UTC'
39+
default_timezone: 'UTC'
40+

src/main/java/org/embulk/output/sftp/SftpFileOutput.java

Lines changed: 83 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.embulk.spi.unit.LocalFile;
1818
import org.slf4j.Logger;
1919

20+
import java.lang.Void;
2021
import java.io.File;
2122
import java.io.IOException;
2223
import java.io.OutputStream;
@@ -144,7 +145,7 @@ public void nextFile()
144145

145146
try {
146147
currentFile = newSftpFile(getSftpFileUri(getOutputFilePath()));
147-
currentFileOutputStream = currentFile.getContent().getOutputStream();
148+
currentFileOutputStream = newSftpOutputStream(currentFile);
148149
logger.info("new sftp file: {}", currentFile.getPublicURIString());
149150
}
150151
catch (FileSystemException e) {
@@ -154,14 +155,26 @@ public void nextFile()
154155
}
155156

156157
@Override
157-
public void add(Buffer buffer)
158+
public void add(final Buffer buffer)
158159
{
159160
if (currentFile == null) {
160161
throw new IllegalStateException("nextFile() must be called before poll()");
161162
}
162163

163164
try {
164-
currentFileOutputStream.write(buffer.array(), buffer.offset(), buffer.limit());
165+
Retriable<Void> retriable = new Retriable<Void>() {
166+
public Void execute() throws IOException
167+
{
168+
currentFileOutputStream.write(buffer.array(), buffer.offset(), buffer.limit());
169+
return null;
170+
}
171+
};
172+
try {
173+
withConnectionRetry(retriable);
174+
}
175+
catch (Exception e) {
176+
throw (IOException)e;
177+
}
165178
}
166179
catch (IOException e) {
167180
logger.error(e.getMessage());
@@ -204,18 +217,21 @@ private void closeCurrentFile()
204217

205218
try {
206219
currentFileOutputStream.close();
207-
currentFile.getContent().close();
208-
currentFile.close();
209220
}
210221
catch (IOException e) {
211-
logger.error(e.getMessage());
212-
Throwables.propagate(e);
222+
logger.info(e.getMessage());
213223
}
214-
finally {
215-
fileIndex++;
216-
currentFile = null;
217-
currentFileOutputStream = null;
224+
225+
try {
226+
currentFile.close();
218227
}
228+
catch (FileSystemException e) {
229+
logger.warn(e.getMessage());
230+
}
231+
232+
fileIndex++;
233+
currentFile = null;
234+
currentFileOutputStream = null;
219235
}
220236

221237
private URI getSftpFileUri(String remoteFilePath)
@@ -234,24 +250,25 @@ private String getOutputFilePath()
234250
return pathPrefix + String.format(sequenceFormat, taskIndex, fileIndex) + fileNameExtension;
235251
}
236252

237-
private FileObject newSftpFile(URI sftpUri)
238-
throws FileSystemException
253+
interface Retriable<T>
239254
{
255+
/**
256+
* Execute the operation with the given (or null) return value.
257+
*
258+
* @return any return value from the operation
259+
* @throws Exception
260+
*/
261+
public T execute() throws Exception;
262+
}
263+
264+
private <T> T withConnectionRetry( final Retriable<T> op ) throws Exception {
240265
int count = 0;
241266
while (true) {
242267
try {
243-
FileObject file = manager.resolveFile(sftpUri.toString(), fsOptions);
244-
if (file.getParent().exists()) {
245-
logger.info("parent directory {} exists there", file.getParent());
246-
return file;
247-
}
248-
else {
249-
logger.info("trying to create parent directory {}", file.getParent());
250-
file.getParent().createFolder();
251-
}
268+
return op.execute();
252269
}
253-
catch (FileSystemException e) {
254-
if (++count == maxConnectionRetry) {
270+
catch(final Exception e) {
271+
if (++count > maxConnectionRetry) {
255272
throw e;
256273
}
257274
logger.warn("failed to connect sftp server: " + e.getMessage(), e);
@@ -270,6 +287,48 @@ private FileObject newSftpFile(URI sftpUri)
270287
}
271288
}
272289

290+
private FileObject newSftpFile(final URI sftpUri)
291+
throws FileSystemException
292+
{
293+
Retriable<FileObject> retriable = new Retriable<FileObject>() {
294+
public FileObject execute() throws FileSystemException
295+
{
296+
FileObject file = manager.resolveFile(sftpUri.toString(), fsOptions);
297+
if (file.getParent().exists()) {
298+
logger.info("parent directory {} exists there", file.getParent());
299+
}
300+
else {
301+
logger.info("trying to create parent directory {}", file.getParent());
302+
file.getParent().createFolder();
303+
}
304+
return file;
305+
}
306+
};
307+
try {
308+
return withConnectionRetry(retriable);
309+
}
310+
catch (Exception e) {
311+
throw (FileSystemException)e;
312+
}
313+
}
314+
315+
private OutputStream newSftpOutputStream(final FileObject file)
316+
throws FileSystemException
317+
{
318+
Retriable<OutputStream> retriable = new Retriable<OutputStream>() {
319+
public OutputStream execute() throws FileSystemException
320+
{
321+
return file.getContent().getOutputStream();
322+
}
323+
};
324+
try {
325+
return withConnectionRetry(retriable);
326+
}
327+
catch (Exception e) {
328+
throw (FileSystemException)e;
329+
}
330+
}
331+
273332
private Function<LocalFile, String> localFileToPathString()
274333
{
275334
return new Function<LocalFile, String>()

0 commit comments

Comments
 (0)