Created
November 12, 2016 19:57
-
-
Save brandonlamb/f298207d6fba264972eb2b0d7689b702 to your computer and use it in GitHub Desktop.
Kotlin, Akka, Ehcache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sbux.gred.location.api.model | |
import io.swagger.annotations.ApiModelProperty | |
data class LocationTime( | |
@ApiModelProperty(example = "7339", name = "locationNumber") | |
var locationNumber: Int? = 0, | |
@ApiModelProperty(example = "01:01:01", name = "time") | |
var time: String? = "" | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns="http://maven.apache.org/POM/4.0.0" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>com.sbux.gred.api</groupId> | |
<artifactId>location-time</artifactId> | |
<name>GRED Location Time v1</name> | |
<version>1.0-SNAPSHOT</version> | |
<packaging>war</packaging> | |
<parent> | |
<groupId>com.sbux.gred</groupId> | |
<artifactId>parent</artifactId> | |
<version>1</version> | |
</parent> | |
<properties> | |
<gred.finalName>ROOT</gred.finalName> | |
<findbugs.skip>false</findbugs.skip> | |
<skipTests>true</skipTests> | |
<version.tomee>7.0.1</version.tomee> | |
<version.log4j2>2.6.2</version.log4j2> | |
<version.owner-java8>1.0.9</version.owner-java8> | |
<version.mybatis>3.4.1</version.mybatis> | |
<version.mybatis-cdi>1.0.0-beta3</version.mybatis-cdi> | |
<version.orika>1.5.0-beta0</version.orika> | |
<version.geronimo-json-1.0-spec>1.0-alpha-1</version.geronimo-json-1.0-spec> | |
<version.johnzon>0.9.3-incubating</version.johnzon> | |
<version.junit>4.12</version.junit> | |
<version.baseplate>1.0-SNAPSHOT</version.baseplate> | |
<!--<version.kotlin>1.1-M02</version.kotlin>--> | |
<version.kotlin>1.0.5</version.kotlin> | |
<version.kdoc>0.12.1230</version.kdoc> | |
<version.kotlin-reflect>1.0.3</version.kotlin-reflect> | |
<version.rxkotlin>0.60.0</version.rxkotlin> | |
<version.kotlin-logging>1.3.2</version.kotlin-logging> | |
<version.kotlin-kovenant>3.3.0</version.kotlin-kovenant> | |
<version.kotlin-kwery>0.13</version.kotlin-kwery> | |
<version.db2>10.5.3</version.db2> | |
<version.akka_actor>2.4.12</version.akka_actor> | |
<version.quasar>0.7.6</version.quasar> | |
<docker.from>jboss/base-jdk:8</docker.from> | |
<docker.maven.plugin.version>0.13.9</docker.maven.plugin.version> | |
<docker.assemblyDescriptorRef>artifact</docker.assemblyDescriptorRef> | |
<docker.image>myfear/swarm-sample:latest</docker.image> | |
</properties> | |
<scm> | |
<connection>scm:git:git@github.starbucks.net:gred-platform/item-api-v1.git</connection> | |
<url>scm:git:git@github.starbucks.net:gred-platform/item-api-v1.git</url> | |
<developerConnection>scm:git:git@github.starbucks.net:gred-platform/item-api-v1.git</developerConnection> | |
<tag>HEAD</tag> | |
</scm> | |
<dependencies> | |
<!-- Java EE 7 dependency --> | |
<dependency> | |
<groupId>javax</groupId> | |
<artifactId>javaee-api</artifactId> | |
<version>7.0</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>javax.cache</groupId> | |
<artifactId>cache-api</artifactId> | |
<version>1.0.0</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.ehcache</groupId> | |
<artifactId>ehcache</artifactId> | |
<version>3.2.0.beta1</version> | |
</dependency> | |
<!-- TomEE --> | |
<dependency> | |
<groupId>org.apache.johnzon</groupId> | |
<artifactId>johnzon-jaxrs</artifactId> | |
<version>${version.johnzon}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.johnzon</groupId> | |
<artifactId>johnzon-mapper</artifactId> | |
<version>${version.johnzon}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.geronimo.specs</groupId> | |
<artifactId>geronimo-json_1.0_spec</artifactId> | |
<version>${version.geronimo-json-1.0-spec}</version> | |
<scope>provided</scope> | |
</dependency> | |
<!-- Kotlin --> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-stdlib</artifactId> | |
<version>${version.kotlin}</version> | |
</dependency> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-reflect</artifactId> | |
<version>${version.kotlin-reflect}</version> | |
</dependency> | |
<!--<dependency>--> | |
<!--<groupId>io.reactivex</groupId>--> | |
<!--<artifactId>rxkotlin</artifactId>--> | |
<!--<version>${version.rxkotlin}</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>com.github.andrewoma.kwery</groupId>--> | |
<!--<artifactId>core</artifactId>--> | |
<!--<version>${version.kotlin-kwery}</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>org.jetbrains.kotlinx</groupId>--> | |
<!--<artifactId>kotlinx-coroutines-generate</artifactId>--> | |
<!--<version>0.1-alpha</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>org.jetbrains.kotlinx</groupId>--> | |
<!--<artifactId>kotlinx-coroutines-async</artifactId>--> | |
<!--<version>0.1-alpha</version>--> | |
<!--</dependency>--> | |
<dependency> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kotlin-test</artifactId> | |
<version>${version.kotlin}</version> | |
<scope>test</scope> | |
</dependency> | |
<!--<dependency>--> | |
<!--<groupId>org.jetbrains.kotlinx</groupId>--> | |
<!--<artifactId>kotlinx-coroutines-rx</artifactId>--> | |
<!--<version>0.1-alpha</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>nl.komponents.kovenant</groupId>--> | |
<!--<artifactId>kovenant</artifactId>--> | |
<!--<version>${version.kotlin-kovenant}</version>--> | |
<!--<type>pom</type>--> | |
<!--</dependency>--> | |
<!-- Logging --> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-api</artifactId> | |
<version>${version.log4j2}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-core</artifactId> | |
<version>${version.log4j2}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-jul</artifactId> | |
<version>${version.log4j2}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-jcl</artifactId> | |
<version>${version.log4j2}</version> | |
<scope>provided</scope> | |
</dependency> | |
<dependency> | |
<groupId>org.apache.logging.log4j</groupId> | |
<artifactId>log4j-web</artifactId> | |
<version>${version.log4j2}</version> | |
<scope>provided</scope> | |
</dependency> | |
<!-- Akka --> | |
<dependency> | |
<groupId>com.typesafe.akka</groupId> | |
<artifactId>akka-actor_2.12</artifactId> | |
<version>${version.akka_actor}</version> | |
</dependency> | |
<!--<dependency>--> | |
<!--<groupId>co.paralleluniverse</groupId>--> | |
<!--<artifactId>quasar-actors</artifactId>--> | |
<!--<version>${version.quasar}</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>co.paralleluniverse</groupId>--> | |
<!--<artifactId>quasar-core</artifactId>--> | |
<!--<version>${version.quasar}</version>--> | |
<!--<classifier>jdk8</classifier>--> | |
<!--<scope>provided</scope>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>co.paralleluniverse</groupId>--> | |
<!--<artifactId>quasar-kotlin</artifactId>--> | |
<!--<version>${version.quasar}</version>--> | |
<!--</dependency>--> | |
<!-- Swagger --> | |
<dependency> | |
<groupId>io.swagger</groupId> | |
<artifactId>swagger-jaxrs</artifactId> | |
<version>1.5.10</version> | |
<exclusions> | |
<!-- API are useless since in javaee-api --> | |
<exclusion> | |
<groupId>javax.ws.rs</groupId> | |
<artifactId>jsr311-api</artifactId> | |
</exclusion> | |
<exclusion> | |
<groupId>javax.validation</groupId> | |
<artifactId>validation-api</artifactId> | |
</exclusion> | |
<!-- not useful for the GUI -> only json for us --> | |
<exclusion> | |
<groupId>com.fasterxml.jackson.dataformat</groupId> | |
<artifactId>jackson-dataformat-xml</artifactId> | |
</exclusion> | |
<exclusion> | |
<groupId>com.fasterxml.jackson.datatype</groupId> | |
<artifactId>jackson-datatype-joda</artifactId> | |
</exclusion> | |
<!-- we don't use reflections so no need of javassist --> | |
<exclusion> | |
<groupId>org.javassist</groupId> | |
<artifactId>javassist</artifactId> | |
</exclusion> | |
<exclusion> | |
<groupId>org.reflections</groupId> | |
<artifactId>reflections</artifactId> | |
</exclusion> | |
<!-- we'll reuse the container one or add an impl as well to your app --> | |
<exclusion> | |
<groupId>org.slf4j</groupId> | |
<artifactId>slf4j-api</artifactId> | |
</exclusion> | |
</exclusions> | |
</dependency> | |
<dependency> | |
<groupId>org.webjars</groupId> | |
<artifactId>swagger-ui</artifactId> | |
<version>2.2.2</version> | |
</dependency> | |
<dependency> | |
<groupId>com.fasterxml.jackson.core</groupId> | |
<artifactId>jackson-core</artifactId> | |
<version>2.8.3</version> | |
</dependency> | |
<!-- GRED common libs --> | |
<!--<dependency>--> | |
<!--<groupId>com.sbux.gred.baseplate</groupId>--> | |
<!--<artifactId>mybatis</artifactId>--> | |
<!--<version>${version.baseplate}</version>--> | |
<!--</dependency>--> | |
<!--<dependency>--> | |
<!--<groupId>com.sbux.gred.baseplate</groupId>--> | |
<!--<artifactId>orika</artifactId>--> | |
<!--<version>${version.baseplate}</version>--> | |
<!--</dependency>--> | |
<dependency> | |
<groupId>com.sbux.gred.baseplate</groupId> | |
<artifactId>ping</artifactId> | |
<version>${version.baseplate}</version> | |
</dependency> | |
<!-- Third Party --> | |
<dependency> | |
<groupId>com.puppycrawl.tools</groupId> | |
<artifactId>checkstyle</artifactId> | |
<version>6.13</version> | |
<scope>test</scope> | |
</dependency> | |
<!--<dependency>--> | |
<!--<groupId>com.fasterxml.jackson.module</groupId>--> | |
<!--<artifactId>jackson-module-kotlin</artifactId>--> | |
<!--<version>2.8.3</version>--> | |
<!--</dependency>--> | |
</dependencies> | |
<build> | |
<finalName>${gred.finalName}</finalName> | |
<sourceDirectory>src/main/kotlin</sourceDirectory> | |
<testSourceDirectory>src/it/kotlin</testSourceDirectory> | |
<testResources> | |
<testResource> | |
<directory>src/it/resources</directory> | |
<filtering>true</filtering> | |
</testResource> | |
</testResources> | |
<resources> | |
<resource> | |
<directory>src/main/resources</directory> | |
<excludes> | |
<exclude>conf/**.*</exclude> | |
</excludes> | |
</resource> | |
<resource> | |
<directory>${project.build.directory}/resources</directory> | |
</resource> | |
</resources> | |
<plugins> | |
<plugin> | |
<artifactId>kotlin-maven-plugin</artifactId> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<version>${version.kotlin}</version> | |
<executions> | |
<execution> | |
<id>compile</id> | |
<phase>compile</phase> | |
<goals> | |
<goal>compile</goal> | |
</goals> | |
</execution> | |
<execution> | |
<id>test-compile</id> | |
<phase>test-compile</phase> | |
<goals> | |
<goal>test-compile</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
<plugin> | |
<groupId>org.jetbrains.kotlin</groupId> | |
<artifactId>kdoc-maven-plugin</artifactId> | |
<version>${version.kdoc}</version> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-dependency-plugin</artifactId> | |
<version>2.10</version> | |
<executions> | |
<execution> | |
<id>copy</id> | |
<phase>package</phase> | |
<goals> | |
<goal>copy</goal> | |
</goals> | |
<configuration> | |
<artifactItems> | |
<artifactItem> | |
<groupId>co.paralleluniverse</groupId> | |
<artifactId>quasar-core</artifactId> | |
<version>${version.quasar}</version> | |
<classifier>jdk8</classifier> | |
<type>jar</type> | |
<outputDirectory>target/dependency</outputDirectory> | |
</artifactItem> | |
</artifactItems> | |
</configuration> | |
</execution> | |
</executions> | |
</plugin> | |
<plugin> | |
<groupId>com.sbux.gred</groupId> | |
<artifactId>gredconfig-maven-plugin</artifactId> | |
<version>1.0.0</version> | |
<configuration> | |
<mergeFiles> | |
<mergeFile> | |
<targetFile>${project.build.directory}/resources/conf/dev.properties</targetFile> | |
<propsFiles> | |
<propsFile>${project.basedir}/src/main/resources/conf/dev.properties/</propsFile> | |
<propsFile>${project.basedir}/src/main/resources/conf/base.properties</propsFile> | |
</propsFiles> | |
</mergeFile> | |
<mergeFile> | |
<targetFile>${project.build.directory}/resources/conf/test.properties</targetFile> | |
<propsFiles> | |
<propsFile>${project.basedir}/src/main/resources/conf/test.properties</propsFile> | |
<propsFile>${project.basedir}/src/main/resources/conf/base.properties</propsFile> | |
</propsFiles> | |
</mergeFile> | |
<mergeFile> | |
<targetFile>${project.build.directory}/resources/conf/cert.properties</targetFile> | |
<propsFiles> | |
<propsFile>${project.basedir}/src/main/resources/conf/cert.properties/</propsFile> | |
<propsFile>${project.basedir}/src/main/resources/conf/base.properties</propsFile> | |
</propsFiles> | |
</mergeFile> | |
<mergeFile> | |
<targetFile>${project.build.directory}/resources/conf/stage.properties</targetFile> | |
<propsFiles> | |
<propsFile>${project.basedir}/src/main/resources/conf/stage.properties/</propsFile> | |
<propsFile>${project.basedir}/src/main/resources/conf/base.properties</propsFile> | |
</propsFiles> | |
</mergeFile> | |
<mergeFile> | |
<targetFile>${project.build.directory}/resources/conf/prod.properties</targetFile> | |
<propsFiles> | |
<propsFile>${project.basedir}/src/main/resources/conf/prod.properties</propsFile> | |
<propsFile>${project.basedir}/src/main/resources/conf/base.properties</propsFile> | |
</propsFiles> | |
</mergeFile> | |
</mergeFiles> | |
</configuration> | |
<executions> | |
<execution> | |
<goals> | |
<goal>generateconfigs</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
<plugin> | |
<groupId>org.apache.tomee.maven</groupId> | |
<artifactId>tomee-maven-plugin</artifactId> | |
<version>${version.tomee}</version> | |
<configuration> | |
<systemVariables> | |
<openejb.classloader.forced-load>io.swagger.</openejb.classloader.forced-load> | |
<!--<log4j.configurationFile>${project.basedir}/src/main/resources/conf/log4j2.xml</log4j.configurationFile>--> | |
<!--<log4j.debug>true</log4j.debug>--> | |
<Xmx>128m</Xmx> | |
<Xms>64m</Xms> | |
</systemVariables> | |
<simpleLog>true</simpleLog> | |
<!--<tomeeGroupId>org.apache.tomee</tomeeGroupId>--> | |
<tomeeGroupId>com.sbux.gred</tomeeGroupId> | |
<tomeeArtifactId>apache-tomee</tomeeArtifactId> | |
<tomeeClassifier>plus</tomeeClassifier> | |
<tomeeVersion>${version.tomee}</tomeeVersion> | |
<tomeeHttpPort>8080</tomeeHttpPort> | |
<webappDefaultConfig>false</webappDefaultConfig> | |
<libs> | |
<!--<lib>remove:batchee</lib>--> | |
<!--<lib>com.ibm.db2.jcc:db2jcc4:${version.db2}</lib>--> | |
<!--<lib>com.ibm.db2.jcc:db2jcc_license_cisuz:${version.db2}</lib>--> | |
<!--<lib>org.apache.logging.log4j:log4j-core:${version.log4j2}</lib>--> | |
<!--<lib>org.apache.logging.log4j:log4j-jul:${version.log4j2}</lib>--> | |
<!--<lib>org.apache.logging.log4j:log4j-jcl:${version.log4j2}</lib>--> | |
<!--<lib>org.apache.logging.log4j:log4j-api:${version.log4j2}</lib>--> | |
<!--<lib>org.apache.logging.log4j:log4j-web:${version.log4j2}</lib>--> | |
<!--<lib>org.elasticsearch:elasticsearch:${version.elasticsearch}</lib>--> | |
</libs> | |
</configuration> | |
</plugin> | |
<!--<plugin>--> | |
<!--<groupId>org.jolokia</groupId>--> | |
<!--<artifactId>docker-maven-plugin</artifactId>--> | |
<!--<version>0.13.9</version>--> | |
<!--</plugin>--> | |
</plugins> | |
</build> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sbux.gred.location.api.controllers | |
import akka.actor.ActorRef | |
import akka.actor.ActorSystem | |
import akka.pattern.PatternsCS.ask | |
import akka.routing.RoundRobinPool | |
import akka.util.Timeout | |
import com.sbux.gred.location.api.model.LocationTime | |
import com.sbux.gred.location.service.TimeService | |
import io.swagger.annotations.Api | |
import io.swagger.annotations.ApiOperation | |
import org.ehcache.Cache | |
import org.ehcache.config.builders.CacheConfigurationBuilder | |
import org.ehcache.config.builders.CacheManagerBuilder | |
import org.ehcache.config.builders.ResourcePoolsBuilder | |
import java.util.concurrent.Executors | |
import java.util.concurrent.TimeUnit | |
import javax.annotation.PostConstruct | |
import javax.annotation.Resource | |
import javax.enterprise.context.ApplicationScoped | |
import javax.sql.DataSource | |
import javax.ws.rs.Consumes | |
import javax.ws.rs.GET | |
import javax.ws.rs.Path | |
import javax.ws.rs.Produces | |
import javax.ws.rs.container.AsyncResponse | |
import javax.ws.rs.container.Suspended | |
import javax.ws.rs.core.MediaType.APPLICATION_JSON | |
import javax.ws.rs.core.Response | |
import javax.ws.rs.PathParam as p | |
@ApplicationScoped | |
@Path("/time") | |
@Consumes(APPLICATION_JSON) | |
@Produces(APPLICATION_JSON) | |
@Api( | |
value = "/time", | |
description = "Location Time Service", | |
tags = arrayOf("location", "time") | |
) | |
open class TimeController { | |
private val actorSystem = ActorSystem.create("locationTime") | |
private lateinit var timeService: ActorRef | |
private val executorService = Executors.newFixedThreadPool(5) | |
@Resource(name = "java:/comp/env/jdbc/IbmDb2") private lateinit var ds: DataSource | |
@PostConstruct | |
open fun init() { | |
val cacheManager = CacheManagerBuilder | |
.newCacheManagerBuilder() | |
.withCache( | |
"utcOffset", | |
CacheConfigurationBuilder.newCacheConfigurationBuilder( | |
Any::class.java, | |
Any::class.java, | |
ResourcePoolsBuilder.heap(20000) | |
).build() | |
).build() | |
cacheManager.init() | |
val cache: Cache<Any, Any> = cacheManager.getCache("utcOffset", Any::class.java, Any::class.java) | |
timeService = actorSystem.actorOf( | |
RoundRobinPool(40).props( | |
TimeService | |
.props(ds, cache) | |
.withDispatcher("akka-time.blocking-dispatcher") | |
), | |
"TimeService" | |
) | |
} | |
@GET | |
@Path("{locationNumber: \\d+}") | |
@ApiOperation( | |
value = "Get the local time at the specified location", | |
notes = "Returns the local time at a location", | |
response = LocationTime::class | |
) | |
open fun getTime(@p("locationNumber") locationNumber: Int, @Suspended res: AsyncResponse) { | |
executorService.submit { | |
ask(timeService, TimeService.FindById(locationNumber), Timeout(5, TimeUnit.SECONDS)).thenAccept { | |
res.resume(Response.ok(it).build()) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.sbux.gred.location.service | |
import akka.actor.AbstractLoggingActor | |
import akka.actor.Props | |
import akka.japi.pf.ReceiveBuilder | |
import com.sbux.gred.location.api.model.LocationTime | |
import org.ehcache.Cache | |
import java.time.OffsetDateTime | |
import java.time.ZoneOffset | |
import javax.sql.DataSource | |
class TimeService(private val ds: DataSource, private val cache: Cache<Any, Any>) : AbstractLoggingActor() { | |
data class FindById(internal val locationNumber: Int) | |
init { | |
receive(ReceiveBuilder.match(FindById::class.java, { findById(it) }).build()) | |
} | |
private fun findById(message: FindById) { | |
val x = cache.get(message.locationNumber) | |
val offset = if (x != null) x as Int else getOffset(message.locationNumber) | |
sender().tell( | |
LocationTime( | |
message.locationNumber, | |
OffsetDateTime.now().atZoneSameInstant( | |
ZoneOffset.ofHoursMinutes(offset / 100, offset % 100) | |
).toString() | |
), | |
self() | |
) | |
} | |
private fun getOffset(locationNumber: Int): Int { | |
println("Cache miss $locationNumber") | |
val sql = """ | |
SELECT utc_offset from location where location_number = ? | |
""" | |
val offset = trywr(ds.connection) { | |
val ps = it.prepareStatement(sql) | |
ps.setInt(1, locationNumber) | |
val rs = ps.executeQuery() | |
rs.next() | |
val offset = rs.getInt("UTC_OFFSET") | |
ps.close() | |
offset | |
} | |
cache.put(locationNumber, offset) | |
return offset | |
} | |
companion object { | |
/** | |
* Properties factory method | |
* @param ds DataSource | |
* @return Props | |
*/ | |
fun props(ds: DataSource, cache: Cache<Any, Any>) = Props.create(TimeService::class.java, ds, cache) | |
} | |
} | |
inline fun <T : AutoCloseable, R> trywr(closeable: T, block: (T) -> R): R { | |
try { | |
return block(closeable) | |
} finally { | |
closeable.close() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment