embulk v0.10 API를 사용한 개인 노트

31317 단어 embulktech

개시하다


Embulk 플러그 인은 0.9 ~ 0.10 노트에 해당합니다.
기본적으로 여기Java plugins to catch up with Embulk v0.10 from v0.9에 쓴 내용을 읽으면 됩니다.평소에 자바를 쓰지 않는 자기가 쓰는 노트(눈에 띄는 게 있으면 꼭 알려주세요)
나는 선생님께서 가르쳐 주신 물건을 한데 모으고 싶다

골대

  • 플러그인은'embulk-core'에 의존하지 않습니다(본체의 Jackson 라이브러리와 충돌하는 문제를 피하고 플러그인을 통해 라이브러리 등을 자유롭게 이용할 수 있습니다)
  • 새 API 플러그인

  • embulk-input-s3
  • embulk-input-mixpanel
  • 삽입식 csvparser
  • gradle-embulk-plugins


    v0.API 개발 플러그인 10개를 사용하려면gradle 플러그인으로 제공되는 gradle-embulk-plugins를 사용해야 합니다. 이 플러그인은gradle 버전 6이 필요하기 때문에gradle 버전을 먼저 제공해야 합니다.

    gradle의 업데이트 방법


    gradle의 버전은 6입니다.엑스를 이용하다.최근gradle7을 발매할 것 같지만gradle-embulk-plugins 7.0에 대응하지 못해 6.6에 불과하다.X 계열의 버전을 이용하다.
    최신 버전여기. 확인
    ./gradlew wrapper --gradle-version 6.8.2
    
    처럼 집행하다.

    build.다시 쓰기gradle


    읽으면서 How to migrate old-style build.gradle of your Embulk plugins 플러그인을 다시 쓰는 build.gradle.쓴 대로 가면 된다.4. Add required testCompile if depending on embulk-core:0.9.22+.에 관한 부분은embulk-0.10 이후에 다음과 같이 기재한다.
        testCompile "org.embulk:embulk-deps:0.10.26"
    
    다음 부분은 루비게이지 대신 마븐 센트럴에서 플러그인을 가져올 수 있는 메커니즘을 사용합니다.플러그인을 Maven Central에 업로드하기 전에 먼저 의견을 달아보는 것이 좋습니다(제 생각에는)
    //publishing {
    //    publications {
    //        embulkPluginMaven(MavenPublication) {  // Publish it with "publishEmbulkPluginMavenPublicationToMavenRepository".
    //            from components.java  // Must be "components.java". The dependency modification works only for it.
    //        }
    //    }
    //    repositories {
    //        maven {
    //            url = "${project.buildDir}/mavenPublishLocal"
    //        }
    //    }
    //}
    
    자바를 컴파일할 때 deprecated의 경고를 출력하기 위해 다음과 같은 설정을 추가합니다.
    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:deprecation" << "-Xlint:unchecked"
    }
    
    gradle-embulk-plugins는 플러그인 로드에 필요한 루비 파일을 자동으로 생성하며 기존 플러그인의 파일プラグイン名.rb이 필요하지 않습니다.
    여러 가지 상황(Ruby 구현guess이 있는 경우 다음과 같은 기술을 통해 독자적인 Ruby 파일을gem에 포함할 수 있다.
    gem {
    
        generateRubyCode = false  // Avoiding generate lib/embulk/parser/jsonpath.rb
        into("lib/embulk/parser/") {
          from "lib/embulk/parser/jsonpath.rb"
        }
        into("lib/embulk/guess/") {
          from "lib/embulk/guess/jsonpath.rb"
        }
    

    Java 우선 적용


    import 다시 쓰기


    기존embulk-core에서 총집합된 클래스는 embulk-util-configembulk-util-timestamp 등 다른 라이브러리로 분할되었다.import 문장을 각각 바꿔야 합니다.
    아래의 각본을 만들어 기계적으로 변환한다.
    #!/bin/bash
    
    set -ue
    
    fatal(){
        echo "Fatal Error: $*" >&2
        exit 1
    }
    
    if [ ! -d src ] ; then
      fatal "invalid exec directory"
    fi
    
    find src -name '*.java' -print0 | xargs -0 \
      perl -i -pe 's/import org.embulk.config.Config;/import org.embulk.util.config.Config;/;
                   s/import org.embulk.config.ConfigDefault;/import org.embulk.util.config.ConfigDefault;/;
                   s/import org.embulk.config.Task;/import org.embulk.util.config.Task;/;
                   s/import org.embulk.spi.ColumnConfig;/import org.embulk.util.config.units.ColumnConfig;/;
                   s/import org.embulk.spi.SchemaConfig;/import org.embulk.util.config.units.SchemaConfig;/;
                   s/import com.google.common.base.Optional;/import java.util.Optional;/;
                   s/import org.embulk.spi.util.FileInputInputStream;/import org.embulk.util.file.FileInputInputStream;/;
                   s/import org.embulk.spi.time.TimestampParser;/import org.embulk.util.timestamp.TimestampFormatter;/;
    '
    

    Exec.getModelManager()


    향후 소멸할 것으로 예상되지만, 현재는 엑시클인터넷을 활용해 당분간 회피할 수 있다.ModelManager는 조만간 삭제되며 다른 쓰기 방식을 사용해야 합니다.
    Exec.getModelManager()
    
    ExecInternal.getModelManager
    
    ExecInternal의build를 사용합니다.gradle에서compileOnly "embulk-core"가 필요하지만 그 자체는 추천하지 않습니다.dependencies에 embulk-core를 넣는 것을 최대한 피해야 한다는 것이다.
    테스트에서 ExecInternal을 잠시 사용할 수 있음(v0.11 개발 시 논의할 모습)
    다음 기술은 테스트를 통해서만 ExecInternal을 활용하는 설정입니다.
    dependencies {
        testCompile "org.embulk:embulk-core:0.10.28"
    }    
    

    loadConfig, loadTask

    ConfigMapper, TaskMapper는 각 종류에서 제공하는 map 방법을 이용한다.
    @@ -43,6 +46,7 @@ public class JsonpathParserPlugin
     {
     
         private static final Logger logger = LoggerFactory.getLogger(JsonpathParserPlugin.class);
    +    private static final ConfigMapperFactory CONFIG_MAPPER_FACTORY = ConfigMapperFactory.builder().addDefaultModules().build();
     
         private static final Configuration JSON_PATH_CONFIG = Configuration
                 .builder()
    @@ -94,18 +98,22 @@ public class JsonpathParserPlugin
         @Override
         public void transaction(ConfigSource config, ParserPlugin.Control control)
         {
    -        PluginTask task = config.loadConfig(PluginTask.class);
    +        final ConfigMapper configMapper = CONFIG_MAPPER_FACTORY.createConfigMapper();
    +        final PluginTask task = configMapper.map(config, PluginTask.class);
     
             Schema schema = getSchemaConfig(task).toSchema();
     
    -        control.run(task.dump(), schema);
    +        control.run(task.toTaskSource(), schema); // v0.10 only
         }
     
         @Override
         public void run(TaskSource taskSource, Schema schema,
                 FileInput input, PageOutput output)
         {
    -        PluginTask task = taskSource.loadTask(PluginTask.class);
    +        final TaskMapper taskMapper = CONFIG_MAPPER_FACTORY.createTaskMapper();
    +        final PluginTask task = taskMapper.map(taskSource, PluginTask.class);
    +
    

    고정 의존 라이브러리


    고정 사용./gradlew dependencies --write-locks 버전의 의존 관계

    파일을 잠그는 자세가 있어야 한다


    build.만약gradle을 적절하게 설정했다면 아래 줄을 포함해야 한다
    javax.validation:validation-api:1.1.0.Final
    com.fasterxml.jackson.core:jackson-annotations:2.6.7
    com.fasterxml.jackson.core:jackson-core:2.6.7
    com.fasterxml.jackson.core:jackson-databind:2.6.7
    com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.6.7
    

    이상적이지 않은 설정


    만약 의존 관계가 적절하지 않다면, 예를 들면 다음과 같다.embulk-util-config 사용com.fasterxml.jackson.core:jackson-databind의 2.6.7
    다른 라이브러리의 의존 관계의 영향2.6.7으로 대체2.6.7.2되었다.
    +--- org.embulk:embulk-util-aws-credentials:0.4.0
    |    +--- org.embulk:embulk-util-config:0.1.1 -> 0.2.1
    |    |    +--- javax.validation:validation-api:1.1.0.Final
    |    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.6.7
    |    |    +--- com.fasterxml.jackson.core:jackson-core:2.6.7
    |    |    +--- com.fasterxml.jackson.core:jackson-databind:2.6.7 -> 2.6.7.2 (*)
    |    |    \--- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.6.7
    |    |         +--- com.fasterxml.jackson.core:jackson-core:2.6.7
    |    |         \--- com.fasterxml.jackson.core:jackson-databind:2.6.7 -> 2.6.7.2 (*)
    
    이러한 출력을 진행한 경우 잠금 파일에 기록2.6.7이 아니라 기록2.6.7.2이다.
    com.fasterxml.jackson.core:jackson-databind:2.6.7.2
    
    이러한 상황에서 적절하게 이용exclude하여 의존관계에서 봉인을 배제하고 상기 응당한 자세를 형성하여 설정

    build.gradle 기술의 기본 방침

  • 플러그인에 잭슨에 의존하지 않으면 embulk-util-config에 exclude
  • 를 삽입할 필요가 없습니다
  • embulk-util-config에서 exclude를 진행한 상황에서comple을 명확하게 묘사하여 상술한 모든 가방을 진입시켰다
  • 다음은 @dmikurube선생님의 보충입니다.

    잭슨 버전.


    이하 이외의 잭슨 시스템의 라이브러리 진입embulkPluginRuntime.lockfile한 경우(Embalk v0.9.23도 이동)도 반드시 2.6.7에 고정해야 한다.
    취소(Embalk v0.9 계열 v10.31 이하) v10.32(미발행) 이상 또는 v0.11(미발행)만 대상으로 했다면2.6.7 이외에도 가능하다.2.6.7 이외의 잭슨, 엠벌크 v0을 넣어도.9 가지 동작도 있지만 장담은 없다.운이 좋다.
    com.fasterxml.jackson.core:jackson-annotations
    com.fasterxml.jackson.core:jackson-core
    com.fasterxml.jackson.core:jackson-databind
    com.fasterxml.jackson.datatype:jackson-datatype-jdk8
    

    잭슨


    아래의 진입embulkPluginRuntime.lockfile의 경우 어느 라이브러리에서 이런 진입을 낳고 사용하는지 밝혀야 한다exclude 등은 다음과 같이 고정된 버전이다.
    취소(Embalk v0.9 계열 v10.31 이하) v10.32(미발행) 이상 또는 v0.11(미발행)만 대상으로 한다면 다른 버전도 가능하다.Embalk v0 버전이 추가된 경우에도 마찬가지입니다.9 가지 동작도 있지만 장담은 없다.운이 좋다.
  • com.google.guava:guava => 18.0
  • org.apache.commons:commons-lang3 => 3.4
  • joda-time:joda-time => 2.9.2
  • org.apache.bval:bval-jsr303 => 0.5
  • 자주 exclude로 만들어서 다시 넣을 수 없는 것


    이하 입장embulkPluginRuntime.lockfile한 경우exclude는 입장하지 않아야 한다.
  • org.slf4j:slf4j-api
  • org.msgpack:msgpack-core
  • 버전 고정을 위한 exclude의 경우


    버전 고정slf4j-api을 위해 상기msgpack-coreexclude를 제외한 버전을 고정하려면 compile "..."로 지정한 버전을 다시 설치하는 것을 잊지 마세요.
    잊어버리면 새로운 엠바크 버전은 움직이지 않는다.(이 라이브러리는 필요한 의존 관계가 없기 때문)
    여기까지

    API 호환성


    문서의 since 섹션이 0.10인 경우 새 API, v0이 작성됩니다.9 를 사용할 때는 이 방법을 사용할 수 없다

    TypeModule


    다음 오류가 발생하면 ConfigMapperFactory를 만들 때 add Type Module이 필요합니다.(embulk-util-config:0.3.0 기본값, TypeModule도 추가되었기 때문에 이 수정은 필요 없습니다.)
    Caused by: java.lang.IllegalArgumentException: 
      Can not construct instance of org.embulk.spi.type.Type,
       problem: abstract types either need to be mapped to concrete types,
    
        private static final ConfigMapperFactory CONFIG_MAPPER_FACTORY = ConfigMapperFactory
                .builder()
                .addDefaultModules()
                .addModule(new TypeModule()) // <-- これ
                .build();
    

    탈구바


    다시 쓰기 ImmutableMap


    diff --git a/src/main/java/org/embulk/parser/jsonpath/JsonpathParserPlugin.java b/src/main/java/org/embulk/parser/jsonpath/JsonpathParserPlugin.java
    index 1946175..5bc9746 100644
    --- a/src/main/java/org/embulk/parser/jsonpath/JsonpathParserPlugin.java
    +++ b/src/main/java/org/embulk/parser/jsonpath/JsonpathParserPlugin.java
    @@ -2,8 +2,10 @@ package org.embulk.parser.jsonpath;
     
     import com.fasterxml.jackson.databind.JsonNode;
     import com.fasterxml.jackson.databind.node.JsonNodeType;
    +
    +import java.util.Collections;
    +import java.util.HashMap;
     import java.util.Optional;
    -import com.google.common.collect.ImmutableMap;
     import com.jayway.jsonpath.Configuration;
     import com.jayway.jsonpath.InvalidJsonException;
     import com.jayway.jsonpath.JsonPath;
    @@ -186,15 +188,15 @@ public class JsonpathParserPlugin
     
         private Map<Column, String> createJsonPathMap(PluginTask task, Schema schema)
         {
    -        ImmutableMap.Builder<Column, String> builder = ImmutableMap.builder();
    +        Map<Column, String> columnMap = new HashMap<>();
             for (int i = 0; i < schema.size(); i++) {
                 ColumnConfig config = getSchemaConfig(task).getColumn(i);
                 JsonpathColumnOption option = config.getOption().loadConfig(JsonpathColumnOption.class);
                 if (option.getPath().isPresent()) {
    -                builder.put(schema.getColumn(i), option.getPath().get());
    +                columnMap.put(schema.getColumn(i), option.getPath().get());
                 }
             }
    -        return builder.build();
    +        return Collections.unmodifiableMap(columnMap);
         }
     
         private void skipOrThrow(DataException cause, boolean stopOnInvalidRecord)
    

    ImmutableSet


    diff --git a/src/main/java/org/embulk/parser/jsonpath/ColumnVisitorImpl.java b/src/main/java/org/embulk/parser/jsonpath/ColumnVisitorImpl.java
    index d846ffe..d5aef46 100644
    --- a/src/main/java/org/embulk/parser/jsonpath/ColumnVisitorImpl.java
    +++ b/src/main/java/org/embulk/parser/jsonpath/ColumnVisitorImpl.java
    @@ -3,8 +3,9 @@ package org.embulk.parser.jsonpath;
     import com.fasterxml.jackson.databind.JsonNode;
     
     import java.time.Instant;
    +import java.util.Arrays;
    +import java.util.Collections;
     im#port java.util.Optional;
    -import com.google.common.collect.ImmutableList;
     import org.embulk.parser.jsonpath.JsonpathParserPlugin.PluginTask;
     import org.embulk.parser.jsonpath.JsonpathParserPlugin.TypecastColumnOption;
     import org.embulk.spi.Column;
    @@ -31,8 +32,8 @@ public class ColumnVisitorImpl
             implements ColumnVisitor
     {
         private static final JsonParser JSON_PARSER = new JsonParser();
    -    private static final List<String> BOOL_TRUE_STRINGS = ImmutableList.of("true", "1", "yes", "on", "y", "t");
    -    private static final List<String> BOOL_FALSE_STRINGS = ImmutableList.of("false", "0", "no", "off", "n", "f");
    +    private static final List<String> BOOL_TRUE_STRINGS = Collections.unmodifiableList(Arrays.asList("true", "1", "yes", "on", "y", "t"));
    +    private static final List<String> BOOL_FALSE_STRINGS = Collections.unmodifiableList(Arrays.asList("false", "0", "no", "off", "n", "f"));
     
         protected final PluginTask task;
         protected final Schema schema;
    

    Throwable


    diff --git a/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java b/embulk-core
    /src/main/java/org/embulk/EmbulkEmbed.java
    index af0e88f4..2f98c9b2 100644
    --- a/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java
    +++ b/embulk-core/src/main/java/org/embulk/EmbulkEmbed.java
    @@ -5,7 +5,6 @@ import static com.google.common.base.Preconditions.checkState;
    
     import com.fasterxml.jackson.databind.ObjectMapper;
     import com.google.common.base.Function;
    -import com.google.common.base.Throwables;
     import com.google.common.collect.ImmutableList;
     import com.google.common.collect.Iterables;
     import com.google.inject.Injector;
    @@ -277,7 +276,10 @@ public class EmbulkEmbed {
             try {
                 injector.destroy();
             } catch (Exception ex) {
    -            throw Throwables.propagate(ex);
    +            if (ex instanceof RuntimeException) {
    +                throw (RuntimeException) ex;
    +            }
    +            throw new RuntimeException(ex);
             }
         }
    

    테스트


    embulk 0.1.10-0.1.29까지-L-I의 선택 행위는 0.9와 다르다.
    embulk 0.1.30에서 이런 행위를 수정하였다
    참조여기.(추후 추가)

    0.9와의 호환성


    v0.embulk 0.9로 이동하는 동안 다음 오류가 발생한 경우 10API 작성
    org.embulk.exec.PartialExecutionException: java.lang.RuntimeException: java.lang.NoSuchMethodError: org.embulk.spi.Buffer: method <init>()V not found
    	at org.embulk.exec.BulkLoader$LoaderState.buildPartialExecuteException(BulkLoader.java:340)
    	at org.embulk.exec.BulkLoader.doRun(BulkLoader.java:566)
    	at org.embulk.exec.BulkLoader.access$000(BulkLoader.java:35)
    	at org.embulk.exec.BulkLoader$1.run(BulkLoader.java:353)
    	at org.embulk.exec.BulkLoader$1.run(BulkLoader.java:350)
    	at org.embulk.spi.Exec.doWith(Exec.java:22)
    	at org.embulk.exec.BulkLoader.run(BulkLoader.java:350)
    	at org.embulk.EmbulkEmbed.run(EmbulkEmbed.java:242)
    	at org.embulk.EmbulkRunner.runInternal(EmbulkRunner.java:291)
    	at org.embulk.EmbulkRunner.run(EmbulkRunner.java:155)
    	at org.embulk.cli.EmbulkRun.runSubcommand(EmbulkRun.java:431)
    	at org.embulk.cli.EmbulkRun.run(EmbulkRun.java:90)
    	at org.embulk.cli.Main.main(Main.java:64)
    
    build.gradle에 다음 항목을 추가하여 구축합니다.버전은 0.1.3 이후여야 합니다.
    dependencies {
        // ... snip ..
        compile "org.embulk:embulk-util-file:0.1.3"
    

    Task


    TimestampFormatter.Task


        // From org.embulk.spi.time.TimestampFormatter.Task
        @Config("default_timezone")
        @ConfigDefault("\"UTC\"")
        public String getDefaultTimeZoneId();
    
        // From org.embulk.spi.time.TimestampFormatter.Task
        @Config("default_timestamp_format")
        @ConfigDefault("\"%Y-%m-%d %H:%M:%S.%6N %z\"")
        public String getDefaultTimestampFormat();
    

    LineEncoder.Task


        // From org.embulk.spi.util.LineEncoder.Task
        @Config("charset")
        @ConfigDefault("\"utf-8\"")
        public Charset getCharset();
    
        // From org.embulk.spi.util.LineEncoder.Task
        @Config("newline")
        @ConfigDefault("\"CRLF\"")
        public Newline getNewline();
    

    좋은 웹페이지 즐겨찾기