swagger에서 api를 정의할 때 Uncaught TypeError: Cannot read property 'withMutations' of null  에러가 발생했다.


이 이유는 api 정의할 때 parameters의 값이 null이기 때문에 발생하는 것이다.




parameters: null,


또는


parameters: ,





=>



parameters:[]


로 하면 동작한다.



Posted by 김용환 '김용환'



$ sudo logrotate /etc/logrotate.d/uwsgi.logrotate


error: skipping "/var/log/sentry/sentry-cron.stderr.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.


이렇게 에러가 나는 이유는 디렉토리의 권한이 너무 많이 있기 때문에 디렉토리의 group, other에 write 권한 을 제외한다면 더 이상 에러가 발생하지 않을 것이다.

Posted by 김용환 '김용환'



vagrant 1.7 버전부터는 기본적으로 SSH 키를 각 머신마다 다르게 준다.

따라서 각 머신에 동일한 SSH 키를 사용하려면 다음 정보를 추가한다.


  config.ssh.insert_key = false



Posted by 김용환 '김용환'

a type was inferred to be `Any`; this may indicate a programming error.


이런 코드를 만난다면, Any 타입으로 먼가 작업할 때 scala 컴파일러가 불평하는 것인데..

이럴 때는 Some으로 감싸면 쉽게 해결된다.




Seq[Seq[Any]] 를 리턴하는 코드라면

실제로는 Some으로 감싸서 (실제로는 Seq[Seq[Some(Any]]) 리턴하게 하면 컴파일 이슈는 사라지고 에러도 발생하지 않는다.

Posted by 김용환 '김용환'



scala-guice는 google-guice를 이용해 scala quill에 맞게 inject를 구현한 간단 코드이다.


libraryDependencies ++= Dependencies.guice


val guice = Seq(
"com.google.inject" % "guice" % "4.2.2",
"com.google.inject.extensions" % "guice-assistedinject" % "4.2.2",
"net.codingwell" %% "scala-guice" % "4.2.2"
)




scala quill 를 사용할 때 데이터 타입 관련해서 Encoder/Decoder로 사용할 Implicits를 구현한다.


package com.google.quill

import java.util.Date

import io.getquill.MappedEncoding
import org.joda.time.DateTime

object Implicits {
implicit val dateTimeDecoder = MappedEncoding[Date, DateTime](Decoders.fromDateField)
implicit val dateTimeEncoder = MappedEncoding[DateTime, Date](_.toDate)
}

object Decoders {
def fromDateField(date: Date): DateTime = {
new DateTime(date)
}
}




데이터베이스에서 사용하는 Orders 클래스를 정의한다.



package com.google.datalake.dao.shopping

import org.joda.time.DateTime

case class Orders(
id: Long,
payment_id: Long,
refund_id: Option[Long],
channel_id: Long,
seller_id: Long,
buyer_id: Option[Long],
buyer_user_id: Long, #...
)



properties 정보

orderDB.dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
orderDB.dataSource.url="jdbc:mysql://test.google.com:3306/buy?useTimezone=true&serverTimezone=UTC&characterEncoding=UTF-8"
orderDB.dataSource.user=xxx
orderDB.dataSource.password=xxx
orderDB.dataSource.cachePrepStmts=true
orderDB.dataSource.prepStmtCacheSize=250




실제 Inject 중심 클래스를 정의한다. google-guice의 AbstractModule를 상속하고 scala-guide의 ScalaModule를 믹싱한 DataBaseModule을 정의한다. 

package com.google.datalake.db.modules

import com.google.inject._
import com.google.datalake.db.SelectOrderDB
import io.getquill.{MysqlJdbcContext, SnakeCase}
import net.codingwell.scalaguice.ScalaModule
import com.google.inject.AbstractModule

class DataBaseModule extends AbstractModule with ScalaModule {

override def configure(): Unit = {
bind(classOf[SelectOrderDB]).asEagerSingleton()
}

@Provides
def provideDataBaseSource(): MysqlJdbcContext[SnakeCase] = {
new MysqlJdbcContext(SnakeCase, "orderDB")
}
}


quill을 이용한 DAO 코드이다. MysqlJdbcContext를 inject해서 사용할 수 있게 한다.


package com.google.datalake.db

import com.google.inject.Inject
import com.google.datalake.dao.shopping.Orders
import io.getquill.{MysqlJdbcContext, SnakeCase}

class SelectOrderDB @Inject()(val ctx: MysqlJdbcContext[SnakeCase]) {

import ctx._

def findById(id: Long) = {
val q = quote {
query[Orders].filter(_.id == lift(id))
}
ctx.run(q)
}

def findByIds(ids: List[Long]): Unit = {
val q = quote {
query[Orders]
.filter(p => liftQuery(ids).contains(p.id))
}
ctx.run(q)
}
}


실제 테스크 코드는 다음과 같다.

package com.google.datalake.db

import com.google.inject.Guice
import com.google.datalake.db.modules.DataBaseModule
import org.scalatest.FunSuite

class SelectOrderDBTest extends FunSuite {

val injector = Guice.createInjector(new DataBaseModule()).getInstance(classOf[SelectOrderDB])
val selectOrderDB = injector.asInstanceOf[SelectOrderDB]

test("find by id") {
val row = selectOrderDB.findById(71721303)

println(row)
}

}







Posted by 김용환 '김용환'


아마존의 Redshift와 구글의 Bigtable을 고려한 적이 있었는데..


"빅 데이터를 지탱하는 기술"이라는 책에서 잠깐 내용을 소개하자면..




중요한 차이점이 하나 있는데. Redshift는 전용(dedicated)인 반면, Bigtable은 멀티테넌트 기반의 공유(shared) 자원 기반이라는 점이다.


따라서 Redshift는 다른 사용자가 사용할 없어서 성능이 안정적이다. 항상 일정한 성능이 나온다.


반면, BigTable은 데이터를 분산하기 때문에 고속화를 실현한다. 다수의 디스크에 데이터가 분산되는 형태를 갖는다. (muti-tenancy 구조이다.)




https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html



https://cloud.google.com/blog/products/gcp/bigquery-under-the-hood


Posted by 김용환 '김용환'


'뱅뱅이론' 


남들이 얘기하길래 찾아본 이론이다.


역시 내 생각과 실제는 다른 것 같다.  



http://www.ddanzi.com/ddanziNews/141355230



http://news.donga.com/3/all/20130730/56737249/1



http://www.fashionchannel.co.kr/main/news.php?table=papernews&query=view&uid=5566

Posted by 김용환 '김용환'


pyenv 정리하다가 실수로 .pyenv를 삭제할 수 있다. 

pip 실행시 아래와 같이 로그가 나오면...


/Users/samuel.kim/.pyenv/shims/pip: line 21: /usr/local/Cellar/pyenv/1.2.7/libexec/pyenv: No such file or directory

/Users/samuel.kim/.pyenv/shims/pip: line 21: /usr/local/Cellar/pyenv/1.2.7/libexec/pyenv: No such file or directory

-bash: /Users/samuel.kim/.spark/venv/bin/python3: No such file or directory

-bash: /Users/samuel.kim/.spark/venv/bin/activate: No such file or directory





 pyenv rehash를 실행하면 pyenv 환경이 제대로 되고 위 에러가 발생하지 않는다.

Posted by 김용환 '김용환'


늘 자주 사용하긴 하지만 


kafka-01.internal.google.com에서 kafka-20.internal.google.com까지의 ip 주소를 얻고 싶다면 



number=0; for i in $(seq 1 20); do if [ $i -le 9 ]; then number=0$i ; else number=$i  ; fi ; ping -c1 -t 1 kafka-$number.internal.google.com  ; done



결과는 나오지만 지저분하게 나오려면 다음처럼 awk를 써서 처음 라인의 호스트와 ip만 나오게 한다.




number=0; for i in $(seq 1 20); do if [ $i -le 9 ]; then number=0$i ; else number=$i  ;fi ; ping -c1 -t 1 kafkatest-$numberr.internal.google.com | awk 'NR==1{print $2$3 ; exit}'  ; done



kafkatest-17.internal.google.com(1.1.1.1

...

Posted by 김용환 '김용환'

mysql에서 여러 개의 master의 데이터를 하나의 slave에 저장할 때 multi-source replication 기법을 사용할 수 있다.

mysql replication과 channel 개념 배우는 자료이다.

Open source India - MySQL Labs: Multi-Source Replication from Shivji kumar Jha


https://dev.mysql.com/doc/refman/5.7/en/replication-multi-source-tutorials.html


Posted by 김용환 '김용환'