embulk-output-td 0.1.4 → 0.1.5
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/.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
|
}
|