embulk-output-td 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 +4 -4
- data/.travis.yml +7 -0
- data/CHANGELOG.md +4 -0
- data/README.md +1 -0
- data/build.gradle +5 -1
- data/config/checkstyle/checkstyle.xml +117 -0
- data/embulk-output-td.gemspec +1 -1
- data/gradle/check.gradle +34 -0
- data/src/main/java/com/treasuredata/api/TdApiClient.java +47 -23
- data/src/main/java/com/treasuredata/api/TdApiClientConfig.java +3 -3
- data/src/main/java/com/treasuredata/api/TdApiConstants.java +6 -2
- data/src/main/java/com/treasuredata/api/TdApiExecutionInterruptedException.java +2 -1
- data/src/main/java/com/treasuredata/api/TdApiExecutionTimeoutException.java +2 -1
- data/src/main/java/com/treasuredata/api/model/TDArrayColumnType.java +1 -1
- data/src/main/java/com/treasuredata/api/model/TDBulkImportSession.java +6 -4
- data/src/main/java/com/treasuredata/api/model/TDColumn.java +4 -2
- data/src/main/java/com/treasuredata/api/model/TDColumnTypeDeserializer.java +26 -13
- data/src/main/java/com/treasuredata/api/model/TDDatabase.java +2 -1
- data/src/main/java/com/treasuredata/api/model/TDMapColumnType.java +1 -1
- data/src/main/java/com/treasuredata/api/model/TDTablePermission.java +4 -2
- data/src/main/java/com/treasuredata/api/model/TDTableType.java +2 -1
- data/src/main/java/org/embulk/output/td/FinalizableExecutorService.java +35 -17
- data/src/main/java/org/embulk/output/td/MsgpackGZFileBuilder.java +13 -7
- data/src/main/java/org/embulk/output/td/RecordWriter.java +21 -382
- data/src/main/java/org/embulk/output/td/TdOutputPlugin.java +175 -40
- data/src/main/java/org/embulk/output/td/writer/BooleanFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/DoubleFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/FieldWriter.java +38 -0
- data/src/main/java/org/embulk/output/td/writer/FieldWriterSet.java +206 -0
- data/src/main/java/org/embulk/output/td/writer/LongFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/StringFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampFieldLongDuplicator.java +28 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampLongFieldWriter.java +23 -0
- data/src/main/java/org/embulk/output/td/writer/TimestampStringFieldWriter.java +27 -0
- data/src/main/java/org/embulk/output/td/writer/UnixTimestampFieldDuplicator.java +27 -0
- data/src/main/java/org/embulk/output/td/writer/UnixTimestampLongFieldWriter.java +26 -0
- data/src/test/java/com/treasuredata/api/TestTdApiClient.java +1 -1
- data/src/test/java/org/embulk/output/td/TestRecordWriter.java +198 -0
- data/src/test/java/org/embulk/output/td/TestTdOutputPlugin.java +529 -0
- data/src/test/java/org/embulk/output/td/writer/TestFieldWriterSet.java +146 -0
- metadata +29 -14
- data/src/test/java/org/embulk/output/td/TestFieldWriter.java +0 -105
@@ -1,5 +1,534 @@
|
|
1
1
|
package org.embulk.output.td;
|
2
2
|
|
3
|
+
import com.google.common.collect.ImmutableList;
|
4
|
+
import com.google.common.collect.ImmutableMap;
|
5
|
+
import com.google.common.collect.Lists;
|
6
|
+
import com.treasuredata.api.TdApiClient;
|
7
|
+
import com.treasuredata.api.TdApiConflictException;
|
8
|
+
import com.treasuredata.api.TdApiNotFoundException;
|
9
|
+
import com.treasuredata.api.model.TDBulkImportSession;
|
10
|
+
import com.treasuredata.api.model.TDBulkImportSession.ImportStatus;
|
11
|
+
import com.treasuredata.api.model.TDTable;
|
12
|
+
import com.treasuredata.api.model.TDTableType;
|
13
|
+
import org.embulk.EmbulkTestRuntime;
|
14
|
+
import org.embulk.config.CommitReport;
|
15
|
+
import org.embulk.config.ConfigDiff;
|
16
|
+
import org.embulk.config.ConfigException;
|
17
|
+
import org.embulk.config.ConfigSource;
|
18
|
+
import org.embulk.config.TaskSource;
|
19
|
+
import org.embulk.output.td.TdOutputPlugin.Mode;
|
20
|
+
import org.embulk.output.td.TdOutputPlugin.PluginTask;
|
21
|
+
import org.embulk.output.td.TdOutputPlugin.TimestampColumnOption;
|
22
|
+
import org.embulk.output.td.TdOutputPlugin.UnixTimestampUnit;
|
23
|
+
import org.embulk.output.td.writer.FieldWriterSet;
|
24
|
+
import org.embulk.spi.Exec;
|
25
|
+
import org.embulk.spi.ExecSession;
|
26
|
+
import org.embulk.spi.OutputPlugin;
|
27
|
+
import org.embulk.spi.Schema;
|
28
|
+
import org.embulk.spi.SchemaConfigException;
|
29
|
+
import org.embulk.spi.TransactionalPageOutput;
|
30
|
+
import org.embulk.spi.type.Type;
|
31
|
+
import org.embulk.spi.type.Types;
|
32
|
+
import org.junit.Before;
|
33
|
+
import org.junit.Rule;
|
34
|
+
import org.junit.Test;
|
35
|
+
import org.slf4j.Logger;
|
36
|
+
|
37
|
+
import java.util.List;
|
38
|
+
|
39
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.COMMITTED;
|
40
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.COMMITTING;
|
41
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.PERFORMING;
|
42
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.READY;
|
43
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.UNKNOWN;
|
44
|
+
import static com.treasuredata.api.model.TDBulkImportSession.ImportStatus.UPLOADING;
|
45
|
+
import static org.junit.Assert.assertEquals;
|
46
|
+
import static org.junit.Assert.assertTrue;
|
47
|
+
import static org.junit.Assert.fail;
|
48
|
+
import static org.mockito.Matchers.any;
|
49
|
+
import static org.mockito.Matchers.anyInt;
|
50
|
+
import static org.mockito.Matchers.anyString;
|
51
|
+
import static org.mockito.Mockito.doNothing;
|
52
|
+
import static org.mockito.Mockito.doReturn;
|
53
|
+
import static org.mockito.Mockito.doThrow;
|
54
|
+
import static org.mockito.Mockito.spy;
|
55
|
+
|
3
56
|
public class TestTdOutputPlugin
|
4
57
|
{
|
58
|
+
@Rule
|
59
|
+
public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
|
60
|
+
|
61
|
+
private ConfigSource config; // not mock
|
62
|
+
private TdOutputPlugin plugin; // mock
|
63
|
+
|
64
|
+
@Before
|
65
|
+
public void createResources()
|
66
|
+
{
|
67
|
+
config = config();
|
68
|
+
plugin = plugin();
|
69
|
+
}
|
70
|
+
|
71
|
+
@Test
|
72
|
+
public void checkUnixTimestampUnit()
|
73
|
+
{
|
74
|
+
{ // sec
|
75
|
+
assertEquals(UnixTimestampUnit.SEC, UnixTimestampUnit.of("sec"));
|
76
|
+
assertEquals(UnixTimestampUnit.SEC.toString(), "sec");
|
77
|
+
assertEquals(UnixTimestampUnit.SEC.getFractionUnit(), 1);
|
78
|
+
}
|
79
|
+
|
80
|
+
{ // milli
|
81
|
+
assertEquals(UnixTimestampUnit.MILLI, UnixTimestampUnit.of("milli"));
|
82
|
+
assertEquals(UnixTimestampUnit.MILLI.toString(), "milli");
|
83
|
+
assertEquals(UnixTimestampUnit.MILLI.getFractionUnit(), 1000);
|
84
|
+
}
|
85
|
+
|
86
|
+
{ // micro
|
87
|
+
assertEquals(UnixTimestampUnit.MICRO, UnixTimestampUnit.of("micro"));
|
88
|
+
assertEquals(UnixTimestampUnit.MICRO.toString(), "micro");
|
89
|
+
assertEquals(UnixTimestampUnit.MICRO.getFractionUnit(), 1000000);
|
90
|
+
}
|
91
|
+
|
92
|
+
{ // nano
|
93
|
+
assertEquals(UnixTimestampUnit.NANO, UnixTimestampUnit.of("nano"));
|
94
|
+
assertEquals(UnixTimestampUnit.NANO.toString(), "nano");
|
95
|
+
assertEquals(UnixTimestampUnit.NANO.getFractionUnit(), 1000000000);
|
96
|
+
}
|
97
|
+
|
98
|
+
{ // invalid_unit
|
99
|
+
try {
|
100
|
+
UnixTimestampUnit.of("invalid_unit");
|
101
|
+
fail();
|
102
|
+
}
|
103
|
+
catch (Throwable e) {
|
104
|
+
e.printStackTrace();
|
105
|
+
assertTrue(e instanceof ConfigException);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
@Test
|
111
|
+
public void transaction()
|
112
|
+
{
|
113
|
+
doReturn("session_name").when(plugin).buildBulkImportSessionName(any(PluginTask.class), any(ExecSession.class));
|
114
|
+
ConfigDiff configDiff = Exec.newConfigDiff().set("last_session", "session_name");
|
115
|
+
doReturn(configDiff).when(plugin).doRun(any(TdApiClient.class), any(PluginTask.class), any(OutputPlugin.Control.class));
|
116
|
+
Schema schema = schema("time", Types.LONG, "c0", Types.STRING, "c1", Types.STRING);
|
117
|
+
|
118
|
+
{ // auto_create_table is true
|
119
|
+
ConfigSource config = this.config.deepCopy().set("auto_create_table", "true");
|
120
|
+
doNothing().when(plugin).createTableIfNotExists(any(TdApiClient.class), anyString(), anyString());
|
121
|
+
assertEquals("session_name", plugin.transaction(config, schema, 0, new OutputPlugin.Control()
|
122
|
+
{
|
123
|
+
@Override
|
124
|
+
public List<CommitReport> run(TaskSource taskSource)
|
125
|
+
{
|
126
|
+
return Lists.newArrayList(Exec.newCommitReport());
|
127
|
+
}
|
128
|
+
}).get(String.class, "last_session"));
|
129
|
+
}
|
130
|
+
|
131
|
+
{ // auto_create_table is false
|
132
|
+
ConfigSource config = this.config.deepCopy().set("auto_create_table", "false");
|
133
|
+
doNothing().when(plugin).validateTableExists(any(TdApiClient.class), anyString(), anyString());
|
134
|
+
assertEquals("session_name", plugin.transaction(config, schema, 0, new OutputPlugin.Control()
|
135
|
+
{
|
136
|
+
@Override
|
137
|
+
public List<CommitReport> run(TaskSource taskSource)
|
138
|
+
{
|
139
|
+
return Lists.newArrayList(Exec.newCommitReport());
|
140
|
+
}
|
141
|
+
}).get(String.class, "last_session"));
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
@Test
|
146
|
+
public void resume()
|
147
|
+
throws Exception
|
148
|
+
{
|
149
|
+
PluginTask task = pluginTask(config);
|
150
|
+
task.setSessionName("session_name");
|
151
|
+
task.setLoadTargetTableName("my_table");
|
152
|
+
task.setDoUpload(true);
|
153
|
+
doReturn(true).when(plugin).startBulkImportSession(any(TdApiClient.class), anyString(), anyString(), anyString());
|
154
|
+
doNothing().when(plugin).completeBulkImportSession(any(TdApiClient.class), anyString(), anyInt());
|
155
|
+
Schema schema = schema("time", Types.LONG, "c0", Types.STRING, "c1", Types.STRING);
|
156
|
+
|
157
|
+
ConfigDiff configDiff = plugin.resume(task.dump(), schema, 0, new OutputPlugin.Control()
|
158
|
+
{
|
159
|
+
@Override
|
160
|
+
public List<CommitReport> run(TaskSource taskSource)
|
161
|
+
{
|
162
|
+
return Lists.newArrayList(Exec.newCommitReport());
|
163
|
+
}
|
164
|
+
});
|
165
|
+
|
166
|
+
assertEquals("session_name", configDiff.get(String.class, "last_session"));
|
167
|
+
}
|
168
|
+
|
169
|
+
@Test
|
170
|
+
public void cleanup()
|
171
|
+
{
|
172
|
+
PluginTask task = pluginTask(config);
|
173
|
+
task.setSessionName("session_name");
|
174
|
+
task.setLoadTargetTableName("my_table");
|
175
|
+
task.setDoUpload(true);
|
176
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
177
|
+
doNothing().when(client).deleteBulkImportSession(anyString());
|
178
|
+
doReturn(client).when(plugin).newTdApiClient(task);
|
179
|
+
Schema schema = schema("time", Types.LONG, "c0", Types.STRING, "c1", Types.STRING);
|
180
|
+
|
181
|
+
plugin.cleanup(task.dump(), schema, 0, Lists.newArrayList(Exec.newCommitReport()));
|
182
|
+
// no error happens
|
183
|
+
}
|
184
|
+
|
185
|
+
@Test
|
186
|
+
public void checkColumnOptions()
|
187
|
+
{
|
188
|
+
TimestampColumnOption columnOption = config.loadConfig(TimestampColumnOption.class);
|
189
|
+
ImmutableMap<String, TimestampColumnOption> columnOptions = ImmutableMap.of(
|
190
|
+
"c0", columnOption, "c1", columnOption
|
191
|
+
);
|
192
|
+
|
193
|
+
{ // schema includes column options' keys
|
194
|
+
Schema schema = schema("c0", Types.LONG, "c1", Types.LONG);
|
195
|
+
plugin.checkColumnOptions(schema, columnOptions);
|
196
|
+
// no error happens
|
197
|
+
}
|
198
|
+
|
199
|
+
{ // schema doesn't include one of column options' keys
|
200
|
+
Schema schema = schema("c0", Types.LONG);
|
201
|
+
try {
|
202
|
+
plugin.checkColumnOptions(schema, columnOptions);
|
203
|
+
fail();
|
204
|
+
}
|
205
|
+
catch (Throwable t) {
|
206
|
+
assertTrue(t instanceof SchemaConfigException);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
@Test
|
212
|
+
public void newTdApiClient()
|
213
|
+
{
|
214
|
+
{ // no proxy setting
|
215
|
+
PluginTask task = pluginTask(config);
|
216
|
+
try (TdApiClient client = plugin.newTdApiClient(task)) {
|
217
|
+
}
|
218
|
+
// no error happens
|
219
|
+
}
|
220
|
+
|
221
|
+
{ // proxy setting
|
222
|
+
PluginTask task = pluginTask(config.deepCopy()
|
223
|
+
.set("http_proxy", ImmutableMap.of("host", "xxx", "port", "8080")));
|
224
|
+
try (TdApiClient client = plugin.newTdApiClient(task)) {
|
225
|
+
}
|
226
|
+
// no error happens
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
@Test
|
231
|
+
public void createTableIfNotExists()
|
232
|
+
{
|
233
|
+
PluginTask task = pluginTask(config);
|
234
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
235
|
+
|
236
|
+
{ // database exists but table doesn't exist
|
237
|
+
doReturn(null).when(client).createTable(anyString(), anyString());
|
238
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
239
|
+
// no error happens
|
240
|
+
}
|
241
|
+
|
242
|
+
{ // table already exists
|
243
|
+
doThrow(conflict()).when(client).createTable(anyString(), anyString());
|
244
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
245
|
+
// no error happens
|
246
|
+
}
|
247
|
+
|
248
|
+
{ // database and table don't exist
|
249
|
+
{ // createTable -> createDB -> createTable
|
250
|
+
doThrow(notFound()).doReturn(null).when(client).createTable(anyString(), anyString());
|
251
|
+
doReturn(null).when(client).createDatabase(anyString());
|
252
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
253
|
+
// no error happens
|
254
|
+
}
|
255
|
+
|
256
|
+
{ // createTable -> createDB -> createTable
|
257
|
+
doThrow(notFound()).doReturn(null).when(client).createTable(anyString(), anyString());
|
258
|
+
doThrow(conflict()).when(client).createDatabase(anyString());
|
259
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
260
|
+
// no error happens
|
261
|
+
}
|
262
|
+
|
263
|
+
{ // createTable -> createDB -> createTable
|
264
|
+
doThrow(notFound()).doThrow(conflict()).when(client).createTable(anyString(), anyString());
|
265
|
+
doReturn(null).when(client).createDatabase(anyString());
|
266
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
267
|
+
// no error happens
|
268
|
+
}
|
269
|
+
|
270
|
+
{ // createTable -> createDB -> createTable
|
271
|
+
doThrow(notFound()).doThrow(conflict()).when(client).createTable(anyString(), anyString());
|
272
|
+
doThrow(conflict()).when(client).createDatabase(anyString());
|
273
|
+
plugin.createTableIfNotExists(client, "my_db", "my_table");
|
274
|
+
// no error happens
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
@Test
|
280
|
+
public void validateTableExists()
|
281
|
+
{
|
282
|
+
PluginTask task = pluginTask(config);
|
283
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
284
|
+
TDTable table = new TDTable("my_table", TDTableType.LOG, null);
|
285
|
+
|
286
|
+
{ // table exists
|
287
|
+
doReturn(ImmutableList.of(table)).when(client).getTables(anyString());
|
288
|
+
plugin.validateTableExists(client, "my_db", "my_table");
|
289
|
+
// no error happens
|
290
|
+
}
|
291
|
+
|
292
|
+
{ // table doesn't exist
|
293
|
+
doReturn(ImmutableList.of()).when(client).getTables(anyString());
|
294
|
+
try {
|
295
|
+
plugin.validateTableExists(client, "my_db", "my_table");
|
296
|
+
fail();
|
297
|
+
}
|
298
|
+
catch (Throwable t) {
|
299
|
+
assertTrue(t instanceof ConfigException);
|
300
|
+
}
|
301
|
+
}
|
302
|
+
|
303
|
+
{ // database doesn't exist
|
304
|
+
doThrow(notFound()).when(client).getTables(anyString());
|
305
|
+
try {
|
306
|
+
plugin.validateTableExists(client, "my_db", "my_table");
|
307
|
+
fail();
|
308
|
+
}
|
309
|
+
catch (Throwable t) {
|
310
|
+
assertTrue(t instanceof ConfigException);
|
311
|
+
}
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
@Test
|
316
|
+
public void buildBulkImportSessionName()
|
317
|
+
{
|
318
|
+
{ // session option is specified
|
319
|
+
PluginTask task = pluginTask(config.deepCopy().set("session", "my_session"));
|
320
|
+
assertEquals("my_session", plugin.buildBulkImportSessionName(task, Exec.session()));
|
321
|
+
}
|
322
|
+
|
323
|
+
{ // session is not specified as option
|
324
|
+
PluginTask task = pluginTask(config);
|
325
|
+
assertTrue(plugin.buildBulkImportSessionName(task, Exec.session()).startsWith("embulk_"));
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
@Test
|
330
|
+
public void startBulkImportSession()
|
331
|
+
{
|
332
|
+
PluginTask task = pluginTask(config);
|
333
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
334
|
+
doNothing().when(client).createBulkImportSession(anyString(), anyString(), anyString());
|
335
|
+
|
336
|
+
{ // status is uploading and unfrozen
|
337
|
+
doReturn(session(UPLOADING, true)).when(client).getBulkImportSession("my_session");
|
338
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
339
|
+
}
|
340
|
+
|
341
|
+
{ // status is uploading and frozen
|
342
|
+
doReturn(session(UPLOADING, false)).when(client).getBulkImportSession("my_session");
|
343
|
+
assertEquals(true, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
344
|
+
}
|
345
|
+
|
346
|
+
{ // status is performing
|
347
|
+
doReturn(session(PERFORMING, false)).when(client).getBulkImportSession("my_session");
|
348
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
349
|
+
}
|
350
|
+
|
351
|
+
{ // status is ready
|
352
|
+
doReturn(session(READY, false)).when(client).getBulkImportSession("my_session");
|
353
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
354
|
+
}
|
355
|
+
|
356
|
+
{ // status is committing
|
357
|
+
doReturn(session(COMMITTING, false)).when(client).getBulkImportSession("my_session");
|
358
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
359
|
+
}
|
360
|
+
|
361
|
+
{ // status is committed
|
362
|
+
doReturn(session(COMMITTED, false)).when(client).getBulkImportSession("my_session");
|
363
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
364
|
+
}
|
365
|
+
|
366
|
+
{ // status is unkown
|
367
|
+
doReturn(session(UNKNOWN, false)).when(client).getBulkImportSession("my_session");
|
368
|
+
try {
|
369
|
+
plugin.startBulkImportSession(client, "my_session", "my_db", "my_table");
|
370
|
+
fail();
|
371
|
+
}
|
372
|
+
catch (Throwable t) {
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
{ // if createBulkImportSession got 409, it can be ignoreable.
|
377
|
+
doThrow(conflict()).when(client).createBulkImportSession(anyString(), anyString(), anyString());
|
378
|
+
doReturn(session(UPLOADING, true)).when(client).getBulkImportSession("my_session");
|
379
|
+
assertEquals(false, plugin.startBulkImportSession(client, "my_session", "my_db", "my_table"));
|
380
|
+
}
|
381
|
+
}
|
382
|
+
|
383
|
+
@Test
|
384
|
+
public void completeBulkImportSession()
|
385
|
+
{
|
386
|
+
PluginTask task = pluginTask(config);
|
387
|
+
doReturn(session(UNKNOWN, false)).when(plugin).waitForStatusChange(any(TdApiClient.class), anyString(), any(ImportStatus.class), any(ImportStatus.class), anyString());
|
388
|
+
|
389
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
390
|
+
doNothing().when(client).freezeBulkImportSession(anyString());
|
391
|
+
doNothing().when(client).performBulkImportSession(anyString(), anyInt());
|
392
|
+
doNothing().when(client).commitBulkImportSession(anyString());
|
393
|
+
|
394
|
+
{ // uploading + unfreeze
|
395
|
+
doReturn(session(UPLOADING, false)).when(client).getBulkImportSession("my_session");
|
396
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
397
|
+
// no error happens
|
398
|
+
}
|
399
|
+
|
400
|
+
{ // uploading + frozen
|
401
|
+
doReturn(session(UPLOADING, true)).when(client).getBulkImportSession("my_session");
|
402
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
403
|
+
// no error happens
|
404
|
+
}
|
405
|
+
|
406
|
+
{ // performing
|
407
|
+
doReturn(session(PERFORMING, false)).when(client).getBulkImportSession(anyString());
|
408
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
409
|
+
// no error happens
|
410
|
+
}
|
411
|
+
|
412
|
+
{ // ready
|
413
|
+
doReturn(session(READY, false)).when(client).getBulkImportSession(anyString());
|
414
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
415
|
+
// no error happens
|
416
|
+
}
|
417
|
+
|
418
|
+
{ // committing
|
419
|
+
doReturn(session(COMMITTING, false)).when(client).getBulkImportSession(anyString());
|
420
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
421
|
+
// no error happens
|
422
|
+
}
|
423
|
+
|
424
|
+
{ // committed
|
425
|
+
doReturn(session(COMMITTED, false)).when(client).getBulkImportSession(anyString());
|
426
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
427
|
+
// no error happens
|
428
|
+
}
|
429
|
+
|
430
|
+
{ // unknown
|
431
|
+
doReturn(session(UNKNOWN, false)).when(client).getBulkImportSession(anyString());
|
432
|
+
try {
|
433
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
434
|
+
fail();
|
435
|
+
}
|
436
|
+
catch (Throwable t) {
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
440
|
+
{ // if freezeBulkImportSession got 409, it can be ignoreable.
|
441
|
+
doThrow(conflict()).when(client).freezeBulkImportSession(anyString());
|
442
|
+
doReturn(session(UPLOADING, true)).when(client).getBulkImportSession("my_session");
|
443
|
+
plugin.completeBulkImportSession(client, "my_session", 0);
|
444
|
+
// no error happens
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
@Test
|
449
|
+
public void waitForStatusChange()
|
450
|
+
{
|
451
|
+
PluginTask task = pluginTask(config);
|
452
|
+
TdApiClient client = spy(plugin.newTdApiClient(task));
|
453
|
+
|
454
|
+
{ // performing -> ready
|
455
|
+
doReturn(session(PERFORMING, false)).doReturn(session(READY, false)).when(client).getBulkImportSession("my_session");
|
456
|
+
plugin.waitForStatusChange(client, "my_session", PERFORMING, READY, "");
|
457
|
+
}
|
458
|
+
|
459
|
+
{ // committing -> committed
|
460
|
+
doReturn(session(COMMITTING, false)).doReturn(session(COMMITTED, false)).when(client).getBulkImportSession("my_session");
|
461
|
+
plugin.waitForStatusChange(client, "my_session", COMMITTING, COMMITTED, "");
|
462
|
+
}
|
463
|
+
}
|
464
|
+
|
465
|
+
@Test
|
466
|
+
public void open()
|
467
|
+
{
|
468
|
+
PluginTask task = pluginTask(config);
|
469
|
+
task.setSessionName("session_name");
|
470
|
+
task.setLoadTargetTableName("my_table");
|
471
|
+
task.setDoUpload(true);
|
472
|
+
Schema schema = schema("time", Types.LONG, "c0", Types.STRING, "c1", Types.STRING);
|
473
|
+
|
474
|
+
try (TransactionalPageOutput output = plugin.open(task.dump(), schema, 0)) {
|
475
|
+
}
|
476
|
+
|
477
|
+
// no error happens.
|
478
|
+
}
|
479
|
+
|
480
|
+
public static ConfigSource config()
|
481
|
+
{
|
482
|
+
return Exec.newConfigSource()
|
483
|
+
.set("apikey", "xxx")
|
484
|
+
.set("endpoint", "api.treasuredata.com")
|
485
|
+
.set("database", "my_db")
|
486
|
+
.set("table", "my_table");
|
487
|
+
}
|
488
|
+
|
489
|
+
public static Schema schema(Object... nameAndTypes)
|
490
|
+
{
|
491
|
+
Schema.Builder builder = Schema.builder();
|
492
|
+
for (int i = 0; i < nameAndTypes.length; i += 2) {
|
493
|
+
String name = (String) nameAndTypes[i];
|
494
|
+
Type type = (Type) nameAndTypes[i + 1];
|
495
|
+
builder.add(name, type);
|
496
|
+
}
|
497
|
+
return builder.build();
|
498
|
+
}
|
499
|
+
|
500
|
+
public static PluginTask pluginTask(ConfigSource config)
|
501
|
+
{
|
502
|
+
return config.loadConfig(PluginTask.class);
|
503
|
+
}
|
504
|
+
|
505
|
+
public static TdOutputPlugin plugin()
|
506
|
+
{
|
507
|
+
return spy(new TdOutputPlugin());
|
508
|
+
}
|
509
|
+
|
510
|
+
public static FieldWriterSet fieldWriters(Logger log, PluginTask task, Schema schema)
|
511
|
+
{
|
512
|
+
return spy(new FieldWriterSet(log, task, schema));
|
513
|
+
}
|
514
|
+
|
515
|
+
public static RecordWriter recordWriter(PluginTask task, TdApiClient client, FieldWriterSet fieldWriters)
|
516
|
+
{
|
517
|
+
return spy(new RecordWriter(task, 0, client, fieldWriters));
|
518
|
+
}
|
519
|
+
|
520
|
+
static TdApiNotFoundException notFound()
|
521
|
+
{
|
522
|
+
return new TdApiNotFoundException(404, "not found".getBytes());
|
523
|
+
}
|
524
|
+
|
525
|
+
static TdApiConflictException conflict()
|
526
|
+
{
|
527
|
+
return new TdApiConflictException(409, "conflict".getBytes());
|
528
|
+
}
|
529
|
+
|
530
|
+
private static TDBulkImportSession session(ImportStatus status, boolean uploadFrozen)
|
531
|
+
{
|
532
|
+
return new TDBulkImportSession("my_session", "my_db", "my_table", status, uploadFrozen, "0", 0, 0, 0, 0);
|
533
|
+
}
|
5
534
|
}
|