embulk-output-key_to_redis 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 57b3d726f99858c48efbd8330847c5559aefeeb0
4
+ data.tar.gz: 47c6ffb23ff8fe4855b3ae454a934e99f1e82b8e
5
+ SHA512:
6
+ metadata.gz: a1414c7c8d0a857993158ef9676928eb0669fe127b89806867c8e6b961869a5b2e1e44be43841332522a30298b417c223e3786aa567de9daf975d1c96d4f647c
7
+ data.tar.gz: d681bb485688f4c644765fd0c3725b1b7c099b5da1d71e8b11c1c89fbc01c758cce26b322d0b878c4e9815f158f7b69b978095b6a992ea6dc4a2a5d839835e1d
data/.gitignore ADDED
@@ -0,0 +1,80 @@
1
+ /pkg/
2
+ /tmp/
3
+ *.gemspec
4
+ .gradle/
5
+ /classpath/
6
+ build/
7
+ .idea
8
+ /.settings/
9
+ /.metadata/
10
+ .classpath
11
+ .project
12
+
13
+ .settings
14
+ .classpath
15
+ .project
16
+ *.iml
17
+ *.ipr
18
+ *.iws
19
+ dist/
20
+ lib_managed/
21
+ project/boot/
22
+ project/plugins/project/
23
+ target/
24
+
25
+ # use glob syntax.
26
+ syntax: glob
27
+ *.ser
28
+ *.class
29
+ *~
30
+ *.bak
31
+ #*.off
32
+ *.old
33
+
34
+ # eclipse conf file
35
+ .settings
36
+ .classpath
37
+ .project
38
+ .manager
39
+ .scala_dependencies
40
+
41
+ # idea
42
+ .idea
43
+ *.iml
44
+
45
+ # building
46
+ target
47
+ build
48
+ null
49
+ tmp*
50
+ temp*
51
+ !templates/
52
+ dist
53
+ test-output
54
+ build.log
55
+
56
+ # other scm
57
+ .svn
58
+ .CVS
59
+ .hg*
60
+
61
+ # switch to regexp syntax.
62
+ # syntax: regexp
63
+ # ^\.pc/
64
+
65
+ #SHITTY output not in target directory
66
+ build.log
67
+ .DS_Store
68
+ derby.log
69
+
70
+ *.db
71
+
72
+ .lib
73
+ sbt
74
+
75
+ logs
76
+ sandbox/db
77
+
78
+
79
+ .ensime*⏎
80
+ project/project/
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ MIT License
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # Key To Redis output plugin for Embulk
2
+
3
+ Output the aggregated key into set of the Redis plugin.
4
+
5
+ This plugin is designed to extract data set diff files used with the combination in below use cases.
6
+
7
+ 1. Use this plugin and output specified key's to redis.
8
+ - this plugin.
9
+ 2. Input another data source and use filter key_in_redis plugin with specified key's then filtered the key's (or that hash).
10
+ - https://github.com/smdmts/embulk-filter-key_in_redis
11
+
12
+
13
+ ## Overview
14
+
15
+ * **Plugin type**: output
16
+ * **Load all or nothing**: no
17
+ * **Resume supported**: no
18
+ * **Cleanup supported**: no
19
+
20
+ ## Configuration
21
+
22
+
23
+ | name | type | required? | default | description |
24
+ |:-------------------------------------|:------------|:-----------|:-------------------------|:-----------------------|
25
+ | host | string | optional | "127.0.0.1" | redis servers host |
26
+ | port | integer | optional | "6379" | redis servers port |
27
+ | db | integer | optional | "null" | redis servers db |
28
+ | flush_on_start | boolean | optional | "false" | flush on start specified redis servers db |
29
+ | redis_set_key | string | required | | redis of key of set name |
30
+ | appender | string | optional | "-" | multi key of appender |
31
+ | put_as_md5 | boolean | optional | "false" | sadd the value to converted md5 |
32
+ | key_with_index | hash: Map<Int,String> | required with key_with_index or json_key_with_index or only one || index with key name |
33
+ | json_key_with_index | hash: Map<Int,String> | required with key_with_index or json_key_with_index or only one || json columns's expanded key name |
34
+ | default_timezone | string | optional | UTC | |
35
+ | default_timestamp_format | string | optional | %Y-%m-%d %H:%M:%S.%6N | |
36
+
37
+ ## Example
38
+
39
+ - input json
40
+ ```json
41
+ {
42
+ "device_id":"ABC",
43
+ "timestamp_micros":1502590079312009,
44
+ "params":{
45
+ "UserID":"user_id_12345"
46
+ }
47
+ }
48
+ ```
49
+
50
+ - definition's yaml
51
+ ```yaml
52
+ filters:
53
+ - type: expand_json
54
+ json_column_name: record
55
+ root: "$."
56
+ stop_on_invalid_record: false
57
+ expanded_columns:
58
+ - { name: "device_id", type: string }
59
+ - { name: "timestamp_micros", type: long }
60
+ - { name: "params", type: json }
61
+ out:
62
+ type: "key_to_redis"
63
+ redis_set_key: redis_key
64
+ flush_on_start: true
65
+ put_as_md5: false
66
+ appender: "_"
67
+ key_with_index:
68
+ 1: "device_id"
69
+ 2: "timestamp_micros"
70
+ json_key_with_index:
71
+ 3: "UserID"
72
+ ```
73
+
74
+ - output as redis command
75
+ ```
76
+ sadd redis_key "ABC_1502590079312009_user_id_12345"
77
+ ```
78
+
79
+ ## Build
80
+
81
+ ```
82
+ $ ./gradlew gem # -t to watch change of files and rebuild continuously
83
+ ```
data/build.gradle ADDED
@@ -0,0 +1,85 @@
1
+ plugins {
2
+ id "com.jfrog.bintray" version "1.1"
3
+ id "com.github.jruby-gradle.base" version "0.1.5"
4
+ id "java"
5
+ id "scala"
6
+ }
7
+ import com.github.jrubygradle.JRubyExec
8
+ repositories {
9
+ mavenCentral()
10
+ jcenter()
11
+ }
12
+ configurations {
13
+ provided
14
+ }
15
+
16
+ version = "0.1.0"
17
+
18
+ sourceCompatibility = 1.7
19
+ targetCompatibility = 1.7
20
+
21
+ dependencies {
22
+ compile "org.embulk:embulk-core:0.8.26"
23
+ compile "org.scala-lang:scala-library:2.11.11"
24
+ compile group: 'io.circe', name: 'circe-core_2.11', version: '0.8.0'
25
+ compile group: 'io.circe', name: 'circe-generic_2.11', version: '0.8.0'
26
+ compile group: 'io.circe', name: 'circe-parser_2.11', version: '0.8.0'
27
+ compile group: 'com.github.etaty', name: 'rediscala_2.11', version: '1.7.0'
28
+ compile group: 'org.bouncycastle', name: 'bcpkix-jdk15on', version: '1.57'
29
+ testCompile group: 'org.scalatest', name: 'scalatest_2.11', version: '3.0.1'
30
+ provided "org.embulk:embulk-core:0.8.26"
31
+ testCompile "junit:junit:4.+"
32
+ }
33
+
34
+ task classpath(type: Copy, dependsOn: ["jar"]) {
35
+ doFirst { file("classpath").deleteDir() }
36
+ from (configurations.runtime - configurations.provided + files(jar.archivePath))
37
+ into "classpath"
38
+ }
39
+ clean { delete "classpath" }
40
+
41
+ task gem(type: JRubyExec, dependsOn: ["gemspec", "classpath"]) {
42
+ jrubyArgs "-rrubygems/gem_runner", "-eGem::GemRunner.new.run(ARGV)", "build"
43
+ script "${project.name}.gemspec"
44
+ doLast { ant.move(file: "${project.name}-${project.version}.gem", todir: "pkg") }
45
+ }
46
+
47
+ task gemPush(type: JRubyExec, dependsOn: ["gem"]) {
48
+ jrubyArgs "-rrubygems/gem_runner", "-eGem::GemRunner.new.run(ARGV)", "push"
49
+ script "pkg/${project.name}-${project.version}.gem"
50
+ }
51
+
52
+ task "package"(dependsOn: ["gemspec", "classpath"]) {
53
+ doLast {
54
+ println "> Build succeeded."
55
+ println "> You can run embulk with '-L ${file(".").absolutePath}' argument."
56
+ }
57
+ }
58
+
59
+ task gemspec {
60
+ ext.gemspecFile = file("${project.name}.gemspec")
61
+ inputs.file "build.gradle"
62
+ outputs.file gemspecFile
63
+ doLast { gemspecFile.write($/
64
+ Gem::Specification.new do |spec|
65
+ spec.name = "${project.name}"
66
+ spec.version = "${project.version}"
67
+ spec.authors = ["smdmts"]
68
+ spec.summary = %[Key To Redis output plugin for Embulk]
69
+ spec.description = %[Dumps records to Key To Redis.]
70
+ spec.email = ["smdmts@gmail.com"]
71
+ spec.licenses = ["MIT"]
72
+ # TODO set this: spec.homepage = "https://github.com/smdmts/embulk-output-key_to_redis"
73
+
74
+ spec.files = `git ls-files`.split("\n") + Dir["classpath/*.jar"]
75
+ spec.test_files = spec.files.grep(%r"^(test|spec)/")
76
+ spec.require_paths = ["lib"]
77
+
78
+ #spec.add_dependency 'YOUR_GEM_DEPENDENCY', ['~> YOUR_GEM_DEPENDENCY_VERSION']
79
+ spec.add_development_dependency 'bundler', ['~> 1.0']
80
+ spec.add_development_dependency 'rake', ['>= 10.0']
81
+ end
82
+ /$)
83
+ }
84
+ }
85
+ clean { delete "${project.name}.gemspec" }
data/build.sbt ADDED
@@ -0,0 +1,32 @@
1
+ enablePlugins(ScalafmtPlugin)
2
+
3
+ lazy val root = (project in file(".")).settings(
4
+ inThisBuild(
5
+ List(
6
+ organization := "com.example",
7
+ scalaVersion := "2.11.11",
8
+ version := "0.1.0-SNAPSHOT"
9
+ )),
10
+ name := "embulk-key_to_redis",
11
+ scalafmtOnCompile in ThisBuild := true,
12
+ scalafmtTestOnCompile in ThisBuild := true
13
+ )
14
+
15
+ resolvers += Resolver.jcenterRepo
16
+ resolvers += Resolver.sonatypeRepo("releases")
17
+ resolvers += "velvia maven" at "http://dl.bintray.com/velvia/maven"
18
+
19
+ lazy val circeVersion = "0.8.0"
20
+ libraryDependencies ++= Seq(
21
+ "org.jruby" % "jruby-complete" % "1.6.5",
22
+ "org.embulk" % "embulk-core" % "0.8.25",
23
+ "com.github.etaty" %% "rediscala" % "1.7.0",
24
+ "io.circe" %% "circe-core" % circeVersion,
25
+ "io.circe" %% "circe-generic" % circeVersion,
26
+ "io.circe" %% "circe-parser" % circeVersion,
27
+ "org.bouncycastle" % "bcpkix-jdk15on" % "1.57",
28
+ "org.scalacheck" %% "scalacheck" % "1.13.4" % Test,
29
+ "org.scalatest" %% "scalatest" % "3.0.1" % Test,
30
+ "org.scalamock" %% "scalamock-scalatest-support" % "3.6.0" % Test,
31
+ "com.github.alexarchambault" %% "scalacheck-shapeless_1.13" % "1.1.5" % Test
32
+ )
Binary file
@@ -0,0 +1,6 @@
1
+ #Wed Aug 09 01:22:56 JST 2017
2
+ distributionBase=GRADLE_USER_HOME
3
+ distributionPath=wrapper/dists
4
+ zipStoreBase=GRADLE_USER_HOME
5
+ zipStorePath=wrapper/dists
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-all.zip
data/gradlew ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ##############################################################################
4
+ ##
5
+ ## Gradle start up script for UN*X
6
+ ##
7
+ ##############################################################################
8
+
9
+ # Attempt to set APP_HOME
10
+ # Resolve links: $0 may be a link
11
+ PRG="$0"
12
+ # Need this for relative symlinks.
13
+ while [ -h "$PRG" ] ; do
14
+ ls=`ls -ld "$PRG"`
15
+ link=`expr "$ls" : '.*-> \(.*\)$'`
16
+ if expr "$link" : '/.*' > /dev/null; then
17
+ PRG="$link"
18
+ else
19
+ PRG=`dirname "$PRG"`"/$link"
20
+ fi
21
+ done
22
+ SAVED="`pwd`"
23
+ cd "`dirname \"$PRG\"`/" >/dev/null
24
+ APP_HOME="`pwd -P`"
25
+ cd "$SAVED" >/dev/null
26
+
27
+ APP_NAME="Gradle"
28
+ APP_BASE_NAME=`basename "$0"`
29
+
30
+ # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31
+ DEFAULT_JVM_OPTS=""
32
+
33
+ # Use the maximum available, or set MAX_FD != -1 to use that value.
34
+ MAX_FD="maximum"
35
+
36
+ warn ( ) {
37
+ echo "$*"
38
+ }
39
+
40
+ die ( ) {
41
+ echo
42
+ echo "$*"
43
+ echo
44
+ exit 1
45
+ }
46
+
47
+ # OS specific support (must be 'true' or 'false').
48
+ cygwin=false
49
+ msys=false
50
+ darwin=false
51
+ nonstop=false
52
+ case "`uname`" in
53
+ CYGWIN* )
54
+ cygwin=true
55
+ ;;
56
+ Darwin* )
57
+ darwin=true
58
+ ;;
59
+ MINGW* )
60
+ msys=true
61
+ ;;
62
+ NONSTOP* )
63
+ nonstop=true
64
+ ;;
65
+ esac
66
+
67
+ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68
+
69
+ # Determine the Java command to use to start the JVM.
70
+ if [ -n "$JAVA_HOME" ] ; then
71
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72
+ # IBM's JDK on AIX uses strange locations for the executables
73
+ JAVACMD="$JAVA_HOME/jre/sh/java"
74
+ else
75
+ JAVACMD="$JAVA_HOME/bin/java"
76
+ fi
77
+ if [ ! -x "$JAVACMD" ] ; then
78
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79
+
80
+ Please set the JAVA_HOME variable in your environment to match the
81
+ location of your Java installation."
82
+ fi
83
+ else
84
+ JAVACMD="java"
85
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86
+
87
+ Please set the JAVA_HOME variable in your environment to match the
88
+ location of your Java installation."
89
+ fi
90
+
91
+ # Increase the maximum file descriptors if we can.
92
+ if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93
+ MAX_FD_LIMIT=`ulimit -H -n`
94
+ if [ $? -eq 0 ] ; then
95
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96
+ MAX_FD="$MAX_FD_LIMIT"
97
+ fi
98
+ ulimit -n $MAX_FD
99
+ if [ $? -ne 0 ] ; then
100
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
101
+ fi
102
+ else
103
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104
+ fi
105
+ fi
106
+
107
+ # For Darwin, add options to specify how the application appears in the dock
108
+ if $darwin; then
109
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110
+ fi
111
+
112
+ # For Cygwin, switch paths to Windows format before running java
113
+ if $cygwin ; then
114
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116
+ JAVACMD=`cygpath --unix "$JAVACMD"`
117
+
118
+ # We build the pattern for arguments to be converted via cygpath
119
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120
+ SEP=""
121
+ for dir in $ROOTDIRSRAW ; do
122
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
123
+ SEP="|"
124
+ done
125
+ OURCYGPATTERN="(^($ROOTDIRS))"
126
+ # Add a user-defined pattern to the cygpath arguments
127
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129
+ fi
130
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
131
+ i=0
132
+ for arg in "$@" ; do
133
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135
+
136
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138
+ else
139
+ eval `echo args$i`="\"$arg\""
140
+ fi
141
+ i=$((i+1))
142
+ done
143
+ case $i in
144
+ (0) set -- ;;
145
+ (1) set -- "$args0" ;;
146
+ (2) set -- "$args0" "$args1" ;;
147
+ (3) set -- "$args0" "$args1" "$args2" ;;
148
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154
+ esac
155
+ fi
156
+
157
+ # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158
+ function splitJvmOpts() {
159
+ JVM_OPTS=("$@")
160
+ }
161
+ eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162
+ JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163
+
164
+ # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
165
+ if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
166
+ cd "$(dirname "$0")"
167
+ fi
168
+
169
+ exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
data/gradlew.bat ADDED
@@ -0,0 +1,84 @@
1
+ @if "%DEBUG%" == "" @echo off
2
+ @rem ##########################################################################
3
+ @rem
4
+ @rem Gradle startup script for Windows
5
+ @rem
6
+ @rem ##########################################################################
7
+
8
+ @rem Set local scope for the variables with windows NT shell
9
+ if "%OS%"=="Windows_NT" setlocal
10
+
11
+ set DIRNAME=%~dp0
12
+ if "%DIRNAME%" == "" set DIRNAME=.
13
+ set APP_BASE_NAME=%~n0
14
+ set APP_HOME=%DIRNAME%
15
+
16
+ @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17
+ set DEFAULT_JVM_OPTS=
18
+
19
+ @rem Find java.exe
20
+ if defined JAVA_HOME goto findJavaFromJavaHome
21
+
22
+ set JAVA_EXE=java.exe
23
+ %JAVA_EXE% -version >NUL 2>&1
24
+ if "%ERRORLEVEL%" == "0" goto init
25
+
26
+ echo.
27
+ echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28
+ echo.
29
+ echo Please set the JAVA_HOME variable in your environment to match the
30
+ echo location of your Java installation.
31
+
32
+ goto fail
33
+
34
+ :findJavaFromJavaHome
35
+ set JAVA_HOME=%JAVA_HOME:"=%
36
+ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37
+
38
+ if exist "%JAVA_EXE%" goto init
39
+
40
+ echo.
41
+ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42
+ echo.
43
+ echo Please set the JAVA_HOME variable in your environment to match the
44
+ echo location of your Java installation.
45
+
46
+ goto fail
47
+
48
+ :init
49
+ @rem Get command-line arguments, handling Windows variants
50
+
51
+ if not "%OS%" == "Windows_NT" goto win9xME_args
52
+
53
+ :win9xME_args
54
+ @rem Slurp the command line arguments.
55
+ set CMD_LINE_ARGS=
56
+ set _SKIP=2
57
+
58
+ :win9xME_args_slurp
59
+ if "x%~1" == "x" goto execute
60
+
61
+ set CMD_LINE_ARGS=%*
62
+
63
+ :execute
64
+ @rem Setup the command line
65
+
66
+ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67
+
68
+ @rem Execute Gradle
69
+ "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70
+
71
+ :end
72
+ @rem End local scope for the variables with windows NT shell
73
+ if "%ERRORLEVEL%"=="0" goto mainEnd
74
+
75
+ :fail
76
+ rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77
+ rem the _cmd.exe /c_ return code!
78
+ if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79
+ exit /b 1
80
+
81
+ :mainEnd
82
+ if "%OS%"=="Windows_NT" endlocal
83
+
84
+ :omega
@@ -0,0 +1,3 @@
1
+ Embulk::JavaPlugin.register_output(
2
+ "key_to_redis", "org.embulk.output.key_to_redis.KeyToRedisOutputPlugin",
3
+ File.expand_path('../../../../classpath', __FILE__))
@@ -0,0 +1 @@
1
+ sbt.version=0.13.15
@@ -0,0 +1,2 @@
1
+ addSbtPlugin("com.lucidchart" % "sbt-scalafmt" % "1.7")
2
+ addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC6")
data/settings.gradle ADDED
@@ -0,0 +1 @@
1
+ rootProject.name = 'embulk-output-key_to_redis'
@@ -0,0 +1,62 @@
1
+ package org.embulk.output.key_to_redis
2
+
3
+ import java.util
4
+
5
+ import org.embulk.config._
6
+ import org.embulk.output.key_to_redis.redis.Redis
7
+ import org.embulk.spi._
8
+
9
+ class KeyToRedisOutputPlugin extends OutputPlugin {
10
+
11
+ override def transaction(config: ConfigSource,
12
+ schema: Schema,
13
+ taskCount: Int,
14
+ control: OutputPlugin.Control): ConfigDiff = {
15
+ val task = config.loadConfig(classOf[PluginTask])
16
+ KeyToRedisOutputPlugin.createRedisInstance(task)
17
+ if (task.getFlushOnStart) {
18
+ KeyToRedisOutputPlugin.redis.foreach(_.flush())
19
+ }
20
+ KeyToRedisOutputPlugin.redis.foreach(_.ping())
21
+ control.run(task.dump())
22
+ KeyToRedisOutputPlugin.redis.foreach(_.close())
23
+ Exec.newConfigDiff
24
+ }
25
+
26
+ override def resume(taskSource: TaskSource,
27
+ schema: Schema,
28
+ taskCount: Int,
29
+ control: OutputPlugin.Control): ConfigDiff =
30
+ throw new UnsupportedOperationException(
31
+ "key to redis output plugin does not support resuming")
32
+
33
+ override def cleanup(taskSource: TaskSource,
34
+ schema: Schema,
35
+ taskCount: Int,
36
+ successTaskReports: util.List[TaskReport]): Unit = {}
37
+
38
+ override def open(taskSource: TaskSource,
39
+ schema: Schema,
40
+ taskIndex: Int): TransactionalPageOutput = {
41
+ val task = taskSource.loadTask(classOf[PluginTask])
42
+ KeyToRedisOutputPlugin.redis match {
43
+ case Some(_) => // nothing to do
44
+ case None => // for map reduce executor.
45
+ KeyToRedisOutputPlugin.createRedisInstance(task)
46
+ }
47
+ PageOutput(taskSource, schema, task.getPutAsMD5)
48
+ }
49
+
50
+ }
51
+
52
+ object KeyToRedisOutputPlugin {
53
+ var redis: Option[Redis] = None
54
+
55
+ def createRedisInstance(task: PluginTask): Unit = {
56
+ KeyToRedisOutputPlugin.redis = Some(
57
+ Redis(task.getRedisSetKey, task.getHost, task.getPort, {
58
+ if (task.getDb.isPresent) Some(task.getDb.get())
59
+ else None
60
+ }))
61
+ }
62
+ }
@@ -0,0 +1,54 @@
1
+ package org.embulk.output.key_to_redis
2
+
3
+ import java.security.MessageDigest
4
+
5
+ import com.google.common.base.Optional
6
+ import org.embulk.config.{TaskReport, TaskSource}
7
+ import org.embulk.output.key_to_redis.column._
8
+ import org.embulk.spi.time.TimestampFormatter
9
+ import org.embulk.spi._
10
+ import org.bouncycastle.util.encoders.Hex
11
+
12
+ import scala.collection.JavaConverters._
13
+
14
+ case class PageOutput(taskSource: TaskSource,
15
+ schema: Schema,
16
+ putAsMD5: Boolean)
17
+ extends TransactionalPageOutput {
18
+ val task: PluginTask = taskSource.loadTask(classOf[PluginTask])
19
+ val digestMd5: MessageDigest = MessageDigest.getInstance("MD5")
20
+
21
+ def timestampFormatter(): TimestampFormatter =
22
+ new TimestampFormatter(task, Optional.absent())
23
+
24
+ override def add(page: Page): Unit = {
25
+ val reader: PageReader = new PageReader(schema)
26
+ reader.setPage(page)
27
+ while (reader.nextRecord()) {
28
+ val setValueVisitor = SetValueColumnVisitor(
29
+ reader,
30
+ timestampFormatter(),
31
+ task.getKeyWithIndex.asScala.toMap,
32
+ task.getJsonKeyWithIndex.asScala.toMap,
33
+ task.getAppender)
34
+ schema.visitColumns(setValueVisitor)
35
+ val value = setValueVisitor.getValue
36
+ if (value.nonEmpty) {
37
+ if (putAsMD5) {
38
+ val hash = Hex.toHexString(
39
+ digestMd5.digest(setValueVisitor.getValue.getBytes()))
40
+ KeyToRedisOutputPlugin.redis.foreach(_.sadd(hash))
41
+ } else {
42
+ KeyToRedisOutputPlugin.redis.foreach(
43
+ _.sadd(setValueVisitor.getValue))
44
+ }
45
+ }
46
+ }
47
+ reader.close()
48
+ }
49
+
50
+ override def finish(): Unit = ()
51
+ override def close(): Unit = ()
52
+ override def commit(): TaskReport = Exec.newTaskReport
53
+ override def abort(): Unit = ()
54
+ }
@@ -0,0 +1,44 @@
1
+ package org.embulk.output.key_to_redis
2
+
3
+ import com.google.common.base.Optional
4
+ import org.embulk.config.{Config, ConfigDefault, Task}
5
+ import org.embulk.spi.time.TimestampFormatter
6
+
7
+ trait PluginTask extends Task with TimestampFormatter.Task {
8
+
9
+ @Config("redis_set_key")
10
+ def getRedisSetKey: String
11
+
12
+ @Config("flush_on_start")
13
+ @ConfigDefault("false")
14
+ def getFlushOnStart: Boolean
15
+
16
+ @Config("put_as_md5")
17
+ @ConfigDefault("false")
18
+ def getPutAsMD5: Boolean
19
+
20
+ @Config("key_with_index")
21
+ @ConfigDefault("{}")
22
+ def getKeyWithIndex: java.util.Map[String, String]
23
+
24
+ @Config("json_key_with_index")
25
+ @ConfigDefault("{}")
26
+ def getJsonKeyWithIndex: java.util.Map[String, String]
27
+
28
+ @Config("appender")
29
+ @ConfigDefault("\"-\"")
30
+ def getAppender: String
31
+
32
+ @Config("host")
33
+ @ConfigDefault("\"127.0.0.1\"")
34
+ def getHost: String
35
+
36
+ @Config("port")
37
+ @ConfigDefault("6379")
38
+ def getPort: Int
39
+
40
+ @Config("db")
41
+ @ConfigDefault("null")
42
+ def getDb: Optional[Int]
43
+
44
+ }
@@ -0,0 +1,90 @@
1
+ package org.embulk.output.key_to_redis.column
2
+
3
+ import org.embulk.output.key_to_redis.json.JsonParser
4
+ import org.embulk.spi.time.TimestampFormatter
5
+ import org.embulk.spi.{
6
+ Column,
7
+ PageReader,
8
+ ColumnVisitor => EmbulkColumnVisitor
9
+ }
10
+
11
+ case class SetValueColumnVisitor(reader: PageReader,
12
+ timestampFormatter: TimestampFormatter,
13
+ keyMap: Map[String, String],
14
+ jsonKeyMap: Map[String, String],
15
+ appender: String)
16
+ extends EmbulkColumnVisitor {
17
+ import scala.collection.mutable
18
+ private val recordMap = mutable.Map[String, String]()
19
+
20
+ val parameterKeys: Seq[String] = keyMap.values.toSeq
21
+ val jsonKeys: Seq[String] = jsonKeyMap.values.toSeq
22
+ val sortedKeys: List[String] = {
23
+ val overRapped =
24
+ (keyMap.keys ++ jsonKeyMap.values.toSeq)
25
+ .groupBy(identity)
26
+ .mapValues(_.size)
27
+ .values
28
+ .toSet
29
+ if (overRapped.size > 1) {
30
+ sys.error("same index number is defined.")
31
+ }
32
+ (keyMap ++ jsonKeyMap).toList.sortBy(_._1.toInt).map(_._2)
33
+ }
34
+
35
+ override def timestampColumn(column: Column): Unit =
36
+ value(column, reader.getTimestamp).foreach(v =>
37
+ put(column, timestampFormatter.format(v)))
38
+
39
+ override def stringColumn(column: Column): Unit =
40
+ value(column, reader.getString).foreach { v =>
41
+ put(column, v)
42
+ }
43
+
44
+ override def longColumn(column: Column): Unit =
45
+ value(column, reader.getLong).foreach(v => put(column, v.toString))
46
+
47
+ override def doubleColumn(column: Column): Unit =
48
+ value(column, reader.getDouble).foreach(v => put(column, v.toString))
49
+
50
+ override def booleanColumn(column: Column): Unit =
51
+ value(column, reader.getBoolean).foreach(v => put(column, v.toString))
52
+
53
+ override def jsonColumn(column: Column): Unit =
54
+ value(column, reader.getJson).foreach { v =>
55
+ if (jsonKeys.nonEmpty) {
56
+ val map = JsonParser(v.toJson)
57
+ jsonKeys.foreach { key =>
58
+ map.get(key) match {
59
+ case Some(value) =>
60
+ recordMap.put(key, value)
61
+ case None =>
62
+ }
63
+ }
64
+ }
65
+ put(column, v.toJson)
66
+ }
67
+
68
+ def value[A](column: Column, method: => (Column => A)): Option[A] =
69
+ if (reader.isNull(column)) {
70
+ None
71
+ } else {
72
+ Some(method(column))
73
+ }
74
+
75
+ def put(column: Column, value: String): Unit = {
76
+ if (parameterKeys.contains(column.getName)) {
77
+ recordMap.put(column.getName, value)
78
+ }
79
+ ()
80
+ }
81
+
82
+ def getValue: String = {
83
+ sortedKeys
84
+ .flatMap { key =>
85
+ recordMap.get(key)
86
+ }
87
+ .mkString(appender)
88
+ }
89
+
90
+ }
@@ -0,0 +1,25 @@
1
+ package org.embulk.output.key_to_redis.json
2
+
3
+ import io.circe._
4
+ import io.circe.parser._
5
+
6
+ object JsonParser {
7
+ def apply(json: String): Map[String, String] = {
8
+ decode[Map[String, Json]](json) match {
9
+ case Right(v: Map[String, Json]) =>
10
+ v.map {
11
+ case (key, innerValue) =>
12
+ val value = innerValue.asString
13
+ .orElse(innerValue.asNumber.map(_.toString))
14
+ .orElse(innerValue.asBoolean.map(_.toString))
15
+ .getOrElse("") // empty.
16
+ if (innerValue.isArray | innerValue.isObject) {
17
+ sys.error(s"not supported json type. key=$key value=$innerValue")
18
+ }
19
+ (key, value)
20
+ }
21
+ case _ =>
22
+ sys.error(s"could not parse json. $json")
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,42 @@
1
+ package org.embulk.output.key_to_redis.redis
2
+
3
+ import redis.RedisClient
4
+
5
+ import scala.concurrent._
6
+ import scala.concurrent.duration._
7
+ import scala.util._
8
+
9
+ case class Redis(setKey: String, host: String, port: Int, db: Option[Int]) {
10
+ implicit val actorSystem = akka.actor.ActorSystem(
11
+ "redis-client",
12
+ classLoader = Some(this.getClass.getClassLoader))
13
+ val redis = RedisClient(host, port, db = db)
14
+
15
+ def ping(): String = {
16
+ import scala.concurrent.ExecutionContext.Implicits.global
17
+ val s: Future[String] = redis.ping()
18
+ s.onComplete {
19
+ case Success(result) => result
20
+ case Failure(t) =>
21
+ actorSystem.shutdown()
22
+ throw t
23
+ }
24
+ Await.result(s, 10.minute)
25
+ }
26
+ def sadd(value: String): Long = {
27
+ val s = redis.sadd(setKey, value)
28
+ Await.result(s, 10.minute)
29
+ }
30
+
31
+ def flush(): Boolean = {
32
+ Await.result(redis.flushdb(), 10.minute)
33
+ }
34
+
35
+ def close(): Unit = {
36
+ redis.stop()
37
+ // wait for stopping.
38
+ Thread.sleep(1000)
39
+ actorSystem.shutdown()
40
+ }
41
+
42
+ }
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: embulk-output-key_to_redis
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - smdmts
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ~>
17
+ - !ruby/object:Gem::Version
18
+ version: '1.0'
19
+ name: bundler
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '10.0'
33
+ name: rake
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Dumps records to Key To Redis.
42
+ email:
43
+ - smdmts@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - .gitignore
49
+ - LICENSE.txt
50
+ - README.md
51
+ - build.gradle
52
+ - build.sbt
53
+ - gradle/wrapper/gradle-wrapper.jar
54
+ - gradle/wrapper/gradle-wrapper.properties
55
+ - gradlew
56
+ - gradlew.bat
57
+ - lib/embulk/output/key_to_redis.rb
58
+ - project/build.properties
59
+ - project/plugins.sbt
60
+ - settings.gradle
61
+ - src/main/scala/org/embulk/output/key_to_redis/KeyToRedisOutputPlugin.scala
62
+ - src/main/scala/org/embulk/output/key_to_redis/PageOutput.scala
63
+ - src/main/scala/org/embulk/output/key_to_redis/PluginTask.scala
64
+ - src/main/scala/org/embulk/output/key_to_redis/column/SetValueColumnVisitor.scala
65
+ - src/main/scala/org/embulk/output/key_to_redis/json/JsonParser.scala
66
+ - src/main/scala/org/embulk/output/key_to_redis/redis/Redis.scala
67
+ - src/test/scala/org/embulk/output/key_to_redis/.gitkeep
68
+ - classpath/akka-actor_2.11-2.3.6.jar
69
+ - classpath/bcpkix-jdk15on-1.57.jar
70
+ - classpath/bcprov-jdk15on-1.57.jar
71
+ - classpath/cats-core_2.11-0.9.0.jar
72
+ - classpath/cats-kernel_2.11-0.9.0.jar
73
+ - classpath/cats-macros_2.11-0.9.0.jar
74
+ - classpath/circe-core_2.11-0.8.0.jar
75
+ - classpath/circe-generic_2.11-0.8.0.jar
76
+ - classpath/circe-jawn_2.11-0.8.0.jar
77
+ - classpath/circe-numbers_2.11-0.8.0.jar
78
+ - classpath/circe-parser_2.11-0.8.0.jar
79
+ - classpath/config-1.2.1.jar
80
+ - classpath/embulk-output-key_to_redis-0.1.0.jar
81
+ - classpath/jawn-parser_2.11-0.10.4.jar
82
+ - classpath/machinist_2.11-0.6.1.jar
83
+ - classpath/macro-compat_2.11-1.1.1.jar
84
+ - classpath/rediscala_2.11-1.7.0.jar
85
+ - classpath/scala-library-2.11.11.jar
86
+ - classpath/scala-reflect-2.11.8.jar
87
+ - classpath/scala-stm_2.11-0.7.jar
88
+ - classpath/shapeless_2.11-2.3.2.jar
89
+ - classpath/simulacrum_2.11-0.10.0.jar
90
+ homepage:
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.1.9
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Key To Redis output plugin for Embulk
114
+ test_files: []