Some scala tips.
Sbt
Set log level on demand
set logLevel := Level.Debug
Run single test
testOnly *MySuite* // suite
test-only *MySuite* -- -z "text" // Use Only test case from suite which name contains "text"
Run App in src/test
sbt test:runMain "com.package.Main"
# or specyfying project:
sbt project/test:runMain "com.package.Main"
Exclude transitive dependencies
val alaDependencies = Seq(
("org.organization" %% "common-mongo" % "1.2.3")
.exclude("org.reactivemongo", "reactivemongo_2.13"),
//...
)
Bloop
bloop test foo -o "*CubeCalculatorTest*" -- -z "a single test case" # Just like in sbt
Metals
How to view JSON-RPC logs?
How to set ammonite/ scala version in script
Like that (source):
// scala 2.12.12
// ammonite 2.3.8
It solves bugs like ‘Error fetching Ammonite 2.3.8-4-88785969 for scala 2.12.13’.
Libraries
TODO Checkout / noteworthy
| Libs | Description | Checked |
|---|---|---|
| diffx | Case class diffs (in tests) | ✅ |
| pureconfig | Read HOCON without boilerplate | |
| quill | Tame doobie’s unsafety. |
Slick - Drop tables
def dropTables(db: Database)(implicit ec: ExecutionContext) =
Await.result(
db.run(
DBIO.sequence(
schemas.map(tab =>
sqlu"DROP TABLE IF EXISTS #${tab.baseTableRow.tableName}"
))), 10 seconds)
FS2
Timers
| awakeEvery | awake every X sec |
|---|---|
| awakeDelay | sleep X sec after execution |
| fixedRate | awakeEvery, but emit unit |
| fixedDelay | awakeDelay, but emit unit |
Misc
throttle➡metered
Sangria
Omit / Remove / Ignore output field
It’s called ExcludeFields !
Cannot count how many times I’ve searched for it 🤦♂️.
Akka
- akka-kafka streams compatibility table here
Scala - Language
Regex pattern matching
val regex = raw"hello:(.*)/(.*)".r
"hello:xe/lol" match{
case regex(a,b) => print((a,b))
case _ => print("nic")
}
// ("xe", "lol")
Date formatting
| FormatStyle | Result |
|---|---|
| “yyyy-MM-dd HH:mm” | 2020-12-20 15:26 |
| FormatStyle.LONG | December 20, 2020 |
| FormatStyle.MEDIUM | Dec 20, 2020 |
| FormatStyle.SHORT | 12/20/20 |
| FormatStyle.LONG | December 20, 2020 at 3:26:59 PM Z |
| FormatStyle.MEDIUM | Dec 20, 2020, 3:26:59 PM |
| FormatStyle.SHORT | 12/20/20, 3:26 PM |
| “E, MMM dd, yyyy HH:mm:ss” | Sun, Dec 20, 2020 15:26:59 |
| “E, MMM dd, yyyy” | Sun, Dec 20, 2020 |
| “HH:mm:ss” | 15:26:59 |
| “HH:mm:ss VV” | 15:26:59 Z |
| “HH:mm:ss O” | 15:26:59 GMT |
| ISO_OFFSET_DATE_TIME | 2021-02-25T14:40:37.942581Z |
| formatDateFancy1 | 30th Jul 2021, 7:42 AM |
import java.time.ZonedDateTime
import java.time.format.{DateTimeFormatter,FormatStyle}
// val date = ZonedDateTime.now()
val date = ZonedDateTime.ofInstant(ZonedDateTime.now.toInstant(), ZoneOffset.UTC)
def formatDateFancy1(zdt: ZonedDateTime): String = {
def daySuffix(n: Int) = {
require(n >= 1 && n <= 31, "illegal day of month: " + n)
if (n >= 11 && n <= 13) {
"th";
} else
(n % 10) match {
case 1 => "st"
case 2 => "nd"
case 3 => "rd"
case _ => "th"
}
}
zdt.getDayOfMonth.toString + daySuffix(zdt.getDayOfMonth) + " "
+ zdt.format(DateTimeFormatter.ofPattern("MMM yyyy, K:mm a"))
}
val formatters : List[ZonedDateTime => String] = List(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"),
DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG),
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM),
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT),
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG),
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM),
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT),
DateTimeFormatter.ofPattern("E, MMM dd, yyyy HH:mm:ss"),
DateTimeFormatter.ofPattern("E, MMM dd, yyyy"),
DateTimeFormatter.ofPattern("HH:mm:ss"),
DateTimeFormatter.ofPattern("HH:mm:ss VV"),
DateTimeFormatter.ofPattern("HH:mm:ss O"),
DateTimeFormatter.ISO_OFFSET_DATE_TIME
).map(fmt => (fmt.format _)) :+ (formatDateFancy1 _)
formatters.map(f => f(date)).reduce(_ + "\n" + _)
Other date operations
Set timezone
ZonedDateTime.now().withZoneSameInstant(ZoneOffset.ofTotalSeconds(timeZoneOffsetSeconds))
Ls files
import java.nio.file.{Files,Path,Paths}
import java.util.stream.Collectors
import scala.jdk.CollectionConverters.ListHasAsScala
val ls :List[Path] =Files
.list(Paths.get("."))
.collect(Collectors.toList[Path])
.asScala.toList
ls
Trivial LRU cache
Maybe not the fastest.
import scala.jdk.CollectionConverters.MapHasAsScala
import scala.collection.mutable
import javax.annotation.concurrent.NotThreadSafe
// From https://stackoverflow.com/a/59116615
@NotThreadSafe
class LRUCache[K, V](maxEntries: Int)
extends java.util.LinkedHashMap[K, V](100, .75f, true) {
override def removeEldestEntry(eldest: java.util.Map.Entry[K, V]): Boolean
= size > maxEntries
}
object LRUCache {
def apply[K, V](maxEntries: Int): mutable.Map[K, V]
= new LRUCache[K, V](maxEntries).asScala // thread safe??
}
Comments