embulk-output-kintone 0.3.3 → 0.4.0
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/.github/workflows/ci.yml +11 -4
- data/build.gradle +11 -0
- data/classpath/{embulk-output-kintone-0.3.3.jar → embulk-output-kintone-0.4.0.jar} +0 -0
- data/src/main/java/org/embulk/output/kintone/KintoneColumnOption.java +12 -15
- data/src/main/java/org/embulk/output/kintone/KintoneColumnVisitor.java +186 -211
- data/src/main/java/org/embulk/output/kintone/KintoneMode.java +19 -21
- data/src/main/java/org/embulk/output/kintone/KintoneOutputPlugin.java +41 -54
- data/src/main/java/org/embulk/output/kintone/KintonePageOutput.java +295 -284
- data/src/main/java/org/embulk/output/kintone/PluginTask.java +37 -36
- data/src/test/java/org/embulk/output/kintone/TestKintoneOutputPlugin.java +1 -3
- metadata +3 -3
|
@@ -7,6 +7,14 @@ import com.kintone.client.model.record.FieldType;
|
|
|
7
7
|
import com.kintone.client.model.record.Record;
|
|
8
8
|
import com.kintone.client.model.record.RecordForUpdate;
|
|
9
9
|
import com.kintone.client.model.record.UpdateKey;
|
|
10
|
+
import java.math.BigDecimal;
|
|
11
|
+
import java.util.ArrayList;
|
|
12
|
+
import java.util.Arrays;
|
|
13
|
+
import java.util.Collections;
|
|
14
|
+
import java.util.List;
|
|
15
|
+
import java.util.concurrent.TimeUnit;
|
|
16
|
+
import java.util.stream.Collectors;
|
|
17
|
+
import org.embulk.config.ConfigException;
|
|
10
18
|
import org.embulk.config.TaskReport;
|
|
11
19
|
import org.embulk.spi.Column;
|
|
12
20
|
import org.embulk.spi.Exec;
|
|
@@ -14,313 +22,316 @@ import org.embulk.spi.Page;
|
|
|
14
22
|
import org.embulk.spi.PageReader;
|
|
15
23
|
import org.embulk.spi.Schema;
|
|
16
24
|
import org.embulk.spi.TransactionalPageOutput;
|
|
17
|
-
|
|
18
|
-
import
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
import org.slf4j.Logger;
|
|
26
|
+
import org.slf4j.LoggerFactory;
|
|
27
|
+
|
|
28
|
+
public class KintonePageOutput implements TransactionalPageOutput {
|
|
29
|
+
public static final int UPSERT_BATCH_SIZE = 10000;
|
|
30
|
+
public static final int CHUNK_SIZE = 100;
|
|
31
|
+
private static final Logger LOGGER = LoggerFactory.getLogger(KintonePageOutput.class);
|
|
32
|
+
private final PageReader pageReader;
|
|
33
|
+
private final PluginTask task;
|
|
34
|
+
private KintoneClient client;
|
|
35
|
+
|
|
36
|
+
public KintonePageOutput(PluginTask task, Schema schema) {
|
|
37
|
+
this.pageReader = new PageReader(schema);
|
|
38
|
+
this.task = task;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Override
|
|
42
|
+
public void add(Page page) {
|
|
43
|
+
KintoneMode mode = KintoneMode.getKintoneModeByValue(task.getMode());
|
|
44
|
+
switch (mode) {
|
|
45
|
+
case INSERT:
|
|
46
|
+
insertPage(page);
|
|
47
|
+
break;
|
|
48
|
+
case UPDATE:
|
|
49
|
+
updatePage(page);
|
|
50
|
+
break;
|
|
51
|
+
case UPSERT:
|
|
52
|
+
upsertPage(page);
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
throw new UnsupportedOperationException(String.format("Unknown mode '%s'", task.getMode()));
|
|
36
56
|
}
|
|
57
|
+
}
|
|
37
58
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
switch (mode) {
|
|
43
|
-
case INSERT:
|
|
44
|
-
insertPage(page);
|
|
45
|
-
break;
|
|
46
|
-
case UPDATE:
|
|
47
|
-
updatePage(page);
|
|
48
|
-
break;
|
|
49
|
-
case UPSERT:
|
|
50
|
-
upsertPage(page);
|
|
51
|
-
break;
|
|
52
|
-
default:
|
|
53
|
-
throw new UnsupportedOperationException(String.format(
|
|
54
|
-
"Unknown mode '%s'",
|
|
55
|
-
task.getMode()));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
59
|
+
@Override
|
|
60
|
+
public void finish() {
|
|
61
|
+
// noop
|
|
62
|
+
}
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
64
|
+
@Override
|
|
65
|
+
public void close() {
|
|
66
|
+
if (this.client == null) {
|
|
67
|
+
return;
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (this.client == null) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
try {
|
|
72
|
-
this.client.close();
|
|
73
|
-
}
|
|
74
|
-
catch (Exception e) {
|
|
75
|
-
throw new RuntimeException("kintone throw exception", e);
|
|
76
|
-
}
|
|
69
|
+
try {
|
|
70
|
+
this.client.close();
|
|
71
|
+
} catch (Exception e) {
|
|
72
|
+
throw new RuntimeException("kintone throw exception", e);
|
|
77
73
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Override
|
|
77
|
+
public void abort() {
|
|
78
|
+
// noop
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@Override
|
|
82
|
+
public TaskReport commit() {
|
|
83
|
+
return Exec.newTaskReport();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public interface Consumer<T> {
|
|
87
|
+
void accept(T t);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void connect(final PluginTask task) {
|
|
91
|
+
KintoneClientBuilder builder = KintoneClientBuilder.create("https://" + task.getDomain());
|
|
92
|
+
if (task.getGuestSpaceId().isPresent()) {
|
|
93
|
+
builder.setGuestSpaceId(task.getGuestSpaceId().orElse(-1));
|
|
83
94
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
public TaskReport commit()
|
|
87
|
-
{
|
|
88
|
-
return Exec.newTaskReport();
|
|
95
|
+
if (task.getBasicAuthUsername().isPresent() && task.getBasicAuthPassword().isPresent()) {
|
|
96
|
+
builder.withBasicAuth(task.getBasicAuthUsername().get(), task.getBasicAuthPassword().get());
|
|
89
97
|
}
|
|
90
98
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
if (task.getUsername().isPresent() && task.getPassword().isPresent()) {
|
|
100
|
+
this.client =
|
|
101
|
+
builder.authByPassword(task.getUsername().get(), task.getPassword().get()).build();
|
|
102
|
+
} else if (task.getToken().isPresent()) {
|
|
103
|
+
this.client = builder.authByApiToken(task.getToken().get()).build();
|
|
94
104
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
builder.withBasicAuth(task.getBasicAuthUsername().get(),
|
|
104
|
-
task.getBasicAuthPassword().get());
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (task.getUsername().isPresent() && task.getPassword().isPresent()) {
|
|
108
|
-
this.client = builder
|
|
109
|
-
.authByPassword(task.getUsername().get(), task.getPassword().get())
|
|
110
|
-
.build();
|
|
111
|
-
}
|
|
112
|
-
else if (task.getToken().isPresent()) {
|
|
113
|
-
this.client = builder
|
|
114
|
-
.authByApiToken(task.getToken().get())
|
|
115
|
-
.build();
|
|
116
|
-
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private void execute(Consumer<KintoneClient> operation) {
|
|
108
|
+
connect(task);
|
|
109
|
+
if (this.client != null) {
|
|
110
|
+
operation.accept(this.client);
|
|
111
|
+
} else {
|
|
112
|
+
throw new RuntimeException("Failed to connect to kintone.");
|
|
117
113
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
column.visit(visitor);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
records.add(record);
|
|
145
|
-
if (records.size() == CHUNK_SIZE) {
|
|
146
|
-
client.record().addRecords(task.getAppId(), records);
|
|
147
|
-
records.clear();
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (records.size() > 0) {
|
|
151
|
-
client.record().addRecords(task.getAppId(), records);
|
|
152
|
-
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private void insertPage(final Page page) {
|
|
117
|
+
execute(
|
|
118
|
+
client -> {
|
|
119
|
+
try {
|
|
120
|
+
ArrayList<Record> records = new ArrayList<>();
|
|
121
|
+
pageReader.setPage(page);
|
|
122
|
+
KintoneColumnVisitor visitor =
|
|
123
|
+
new KintoneColumnVisitor(pageReader, task.getColumnOptions());
|
|
124
|
+
while (pageReader.nextRecord()) {
|
|
125
|
+
Record record = new Record();
|
|
126
|
+
visitor.setRecord(record);
|
|
127
|
+
for (Column column : pageReader.getSchema().getColumns()) {
|
|
128
|
+
column.visit(visitor);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
records.add(record);
|
|
132
|
+
if (records.size() == CHUNK_SIZE) {
|
|
133
|
+
client.record().addRecords(task.getAppId(), records);
|
|
134
|
+
records.clear();
|
|
135
|
+
sleep();
|
|
136
|
+
}
|
|
153
137
|
}
|
|
154
|
-
|
|
155
|
-
|
|
138
|
+
if (records.size() > 0) {
|
|
139
|
+
client.record().addRecords(task.getAppId(), records);
|
|
156
140
|
}
|
|
141
|
+
} catch (Exception e) {
|
|
142
|
+
throw new RuntimeException("kintone throw exception", e);
|
|
143
|
+
}
|
|
157
144
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private void updatePage(final Page page) {
|
|
148
|
+
execute(
|
|
149
|
+
client -> {
|
|
150
|
+
try {
|
|
151
|
+
ArrayList<RecordForUpdate> updateRecords = new ArrayList<>();
|
|
152
|
+
pageReader.setPage(page);
|
|
153
|
+
|
|
154
|
+
KintoneColumnVisitor visitor =
|
|
155
|
+
new KintoneColumnVisitor(
|
|
156
|
+
pageReader,
|
|
157
|
+
task.getColumnOptions(),
|
|
158
|
+
task.getUpdateKeyName()
|
|
159
|
+
.orElseThrow(
|
|
160
|
+
() -> new RuntimeException("unreachable"))); // Already validated
|
|
161
|
+
while (pageReader.nextRecord()) {
|
|
162
|
+
Record record = new Record();
|
|
163
|
+
UpdateKey updateKey = new UpdateKey();
|
|
164
|
+
visitor.setRecord(record);
|
|
165
|
+
visitor.setUpdateKey(updateKey);
|
|
166
|
+
for (Column column : pageReader.getSchema().getColumns()) {
|
|
167
|
+
column.visit(visitor);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (updateKey.getValue() == "") {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
record.removeField(updateKey.getField());
|
|
175
|
+
updateRecords.add(new RecordForUpdate(updateKey, record));
|
|
176
|
+
if (updateRecords.size() == CHUNK_SIZE) {
|
|
177
|
+
client.record().updateRecords(task.getAppId(), updateRecords);
|
|
178
|
+
updateRecords.clear();
|
|
179
|
+
sleep();
|
|
180
|
+
}
|
|
193
181
|
}
|
|
194
|
-
|
|
195
|
-
|
|
182
|
+
if (updateRecords.size() > 0) {
|
|
183
|
+
client.record().updateRecords(task.getAppId(), updateRecords);
|
|
196
184
|
}
|
|
185
|
+
} catch (Exception e) {
|
|
186
|
+
throw new RuntimeException("kintone throw exception", e);
|
|
187
|
+
}
|
|
197
188
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
private void upsertPage(final Page page) {
|
|
192
|
+
execute(
|
|
193
|
+
client -> {
|
|
194
|
+
try {
|
|
195
|
+
ArrayList<Record> records = new ArrayList<>();
|
|
196
|
+
ArrayList<UpdateKey> updateKeys = new ArrayList<>();
|
|
197
|
+
pageReader.setPage(page);
|
|
198
|
+
|
|
199
|
+
KintoneColumnVisitor visitor =
|
|
200
|
+
new KintoneColumnVisitor(
|
|
201
|
+
pageReader,
|
|
202
|
+
task.getColumnOptions(),
|
|
203
|
+
task.getUpdateKeyName()
|
|
204
|
+
.orElseThrow(
|
|
205
|
+
() -> new RuntimeException("unreachable"))); // Already validated
|
|
206
|
+
while (pageReader.nextRecord()) {
|
|
207
|
+
Record record = new Record();
|
|
208
|
+
UpdateKey updateKey = new UpdateKey();
|
|
209
|
+
visitor.setRecord(record);
|
|
210
|
+
visitor.setUpdateKey(updateKey);
|
|
211
|
+
for (Column column : pageReader.getSchema().getColumns()) {
|
|
212
|
+
column.visit(visitor);
|
|
213
|
+
}
|
|
214
|
+
records.add(record);
|
|
215
|
+
updateKeys.add(updateKey);
|
|
216
|
+
|
|
217
|
+
if (records.size() == UPSERT_BATCH_SIZE) {
|
|
218
|
+
upsert(records, updateKeys);
|
|
219
|
+
records.clear();
|
|
220
|
+
updateKeys.clear();
|
|
221
|
+
}
|
|
231
222
|
}
|
|
232
|
-
|
|
233
|
-
|
|
223
|
+
if (records.size() > 0) {
|
|
224
|
+
upsert(records, updateKeys);
|
|
234
225
|
}
|
|
226
|
+
} catch (Exception e) {
|
|
227
|
+
throw new RuntimeException("kintone throw exception", e);
|
|
228
|
+
}
|
|
235
229
|
});
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
private void upsert(ArrayList<Record> records, ArrayList<UpdateKey> updateKeys)
|
|
239
|
-
{
|
|
240
|
-
if (records.size() != updateKeys.size()) {
|
|
241
|
-
throw new RuntimeException("records.size() != updateKeys.size()");
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
List<Record> existingRecords = getExistingRecordsByUpdateKey(updateKeys);
|
|
245
|
-
|
|
246
|
-
ArrayList<Record> insertRecords = new ArrayList<>();
|
|
247
|
-
ArrayList<RecordForUpdate> updateRecords = new ArrayList<>();
|
|
248
|
-
for (int i = 0; i < records.size(); i++) {
|
|
249
|
-
Record record = records.get(i);
|
|
250
|
-
UpdateKey updateKey = updateKeys.get(i);
|
|
251
|
-
|
|
252
|
-
if (existsRecord(existingRecords, updateKey)) {
|
|
253
|
-
record.removeField(updateKey.getField());
|
|
254
|
-
updateRecords.add(new RecordForUpdate(updateKey, record));
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
insertRecords.add(record);
|
|
258
|
-
}
|
|
230
|
+
}
|
|
259
231
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (insertRecords.size() > 0) {
|
|
270
|
-
client.record().addRecords(task.getAppId(), insertRecords);
|
|
271
|
-
}
|
|
272
|
-
if (updateRecords.size() > 0) {
|
|
273
|
-
client.record().updateRecords(task.getAppId(), updateRecords);
|
|
274
|
-
}
|
|
232
|
+
private void upsert(ArrayList<Record> records, ArrayList<UpdateKey> updateKeys)
|
|
233
|
+
throws InterruptedException {
|
|
234
|
+
if (records.size() != updateKeys.size()) {
|
|
235
|
+
throw new RuntimeException("records.size() != updateKeys.size()");
|
|
236
|
+
}
|
|
237
|
+
FieldType updateKeyFieldType =
|
|
238
|
+
client.app().getFormFields(task.getAppId()).get(updateKeys.get(0).getField()).getType();
|
|
239
|
+
if (!Arrays.asList(FieldType.SINGLE_LINE_TEXT, FieldType.NUMBER).contains(updateKeyFieldType)) {
|
|
240
|
+
throw new ConfigException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
|
|
275
241
|
}
|
|
276
242
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
243
|
+
List<Record> existingRecords = getExistingRecordsByUpdateKey(updateKeys);
|
|
244
|
+
String updateField = updateKeys.get(0).getField();
|
|
245
|
+
List<String> existingValues =
|
|
246
|
+
existingRecords.stream()
|
|
247
|
+
.map(
|
|
248
|
+
(r) -> {
|
|
249
|
+
switch (updateKeyFieldType) {
|
|
250
|
+
case SINGLE_LINE_TEXT:
|
|
251
|
+
String s = r.getSingleLineTextFieldValue(updateField);
|
|
252
|
+
return s == null ? null : s.toString();
|
|
253
|
+
case NUMBER:
|
|
254
|
+
BigDecimal bd = r.getNumberFieldValue(updateField);
|
|
255
|
+
return bd == null ? null : bd.toPlainString();
|
|
256
|
+
default:
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
.filter(v -> v != null)
|
|
261
|
+
.collect(Collectors.toList());
|
|
262
|
+
|
|
263
|
+
ArrayList<Record> insertRecords = new ArrayList<>();
|
|
264
|
+
ArrayList<RecordForUpdate> updateRecords = new ArrayList<>();
|
|
265
|
+
for (int i = 0; i < records.size(); i++) {
|
|
266
|
+
Record record = records.get(i);
|
|
267
|
+
UpdateKey updateKey = updateKeys.get(i);
|
|
268
|
+
|
|
269
|
+
if (existsRecord(existingValues, updateKey)) {
|
|
270
|
+
record.removeField(updateKey.getField());
|
|
271
|
+
updateRecords.add(new RecordForUpdate(updateKey, record));
|
|
272
|
+
} else {
|
|
273
|
+
insertRecords.add(record);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (insertRecords.size() == CHUNK_SIZE) {
|
|
277
|
+
client.record().addRecords(task.getAppId(), insertRecords);
|
|
278
|
+
insertRecords.clear();
|
|
279
|
+
sleep();
|
|
280
|
+
} else if (updateRecords.size() == CHUNK_SIZE) {
|
|
281
|
+
client.record().updateRecords(task.getAppId(), updateRecords);
|
|
282
|
+
updateRecords.clear();
|
|
283
|
+
sleep();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (insertRecords.size() > 0) {
|
|
287
|
+
client.record().addRecords(task.getAppId(), insertRecords);
|
|
288
|
+
}
|
|
289
|
+
if (updateRecords.size() > 0) {
|
|
290
|
+
client.record().updateRecords(task.getAppId(), updateRecords);
|
|
306
291
|
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
private List<Record> getExistingRecordsByUpdateKey(ArrayList<UpdateKey> updateKeys) {
|
|
295
|
+
String fieldCode = updateKeys.get(0).getField();
|
|
296
|
+
List<String> queryValues =
|
|
297
|
+
updateKeys.stream()
|
|
298
|
+
.filter(k -> k.getValue() != "")
|
|
299
|
+
.map(k -> "\"" + k.getValue().toString() + "\"")
|
|
300
|
+
.collect(Collectors.toList());
|
|
301
|
+
|
|
302
|
+
List<Record> allRecords = new ArrayList<>();
|
|
303
|
+
if (queryValues.isEmpty()) {
|
|
304
|
+
return allRecords;
|
|
305
|
+
}
|
|
306
|
+
String cursorId =
|
|
307
|
+
client
|
|
308
|
+
.record()
|
|
309
|
+
.createCursor(
|
|
310
|
+
task.getAppId(),
|
|
311
|
+
Collections.singletonList(fieldCode),
|
|
312
|
+
fieldCode + " in (" + String.join(",", queryValues) + ")");
|
|
313
|
+
while (true) {
|
|
314
|
+
GetRecordsByCursorResponseBody resp = client.record().getRecordsByCursor(cursorId);
|
|
315
|
+
List<Record> records = resp.getRecords();
|
|
316
|
+
allRecords.addAll(records);
|
|
317
|
+
|
|
318
|
+
if (!resp.hasNext()) {
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return allRecords;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private boolean existsRecord(List<String> distValues, UpdateKey updateKey) {
|
|
326
|
+
return distValues.stream().anyMatch(v -> v.equals(updateKey.getValue().toString()));
|
|
327
|
+
}
|
|
307
328
|
|
|
308
|
-
|
|
309
|
-
{
|
|
310
|
-
|
|
311
|
-
FieldType type = client.app().getFormFields(task.getAppId()).get(fieldCode).getType();
|
|
312
|
-
switch (type) {
|
|
313
|
-
case SINGLE_LINE_TEXT:
|
|
314
|
-
return distRecords
|
|
315
|
-
.stream()
|
|
316
|
-
.anyMatch(d -> d.getSingleLineTextFieldValue(fieldCode).equals(updateKey.getValue().toString()));
|
|
317
|
-
case NUMBER:
|
|
318
|
-
return distRecords
|
|
319
|
-
.stream()
|
|
320
|
-
.anyMatch(d -> d.getNumberFieldValue(fieldCode).toPlainString()
|
|
321
|
-
.equals(updateKey.getValue().toString()));
|
|
322
|
-
default:
|
|
323
|
-
throw new RuntimeException("The update_key must be 'SINGLE_LINE_TEXT' or 'NUMBER'.");
|
|
324
|
-
}
|
|
329
|
+
private void sleep() throws InterruptedException {
|
|
330
|
+
if (!task.getIntervalSeconds().isPresent()) {
|
|
331
|
+
return;
|
|
325
332
|
}
|
|
333
|
+
Integer interval = task.getIntervalSeconds().get();
|
|
334
|
+
LOGGER.info(String.format("sleep %d seconds.", interval));
|
|
335
|
+
TimeUnit.SECONDS.sleep(interval);
|
|
336
|
+
}
|
|
326
337
|
}
|