$ 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 '김용환'
,