This content is not available in your language... So if you don't understand the language... well, at least you can appreciate the pictures of the post, right?
Lately I've noticed that my nginx server is throwing "upstream prematurely closed connection while reading upstream" when reverse proxying my Ktor webapps, and I'm not sure why.
The client (Ktor) fails with "Chunked stream has ended unexpectedly: no chunk size" when nginx throws that error.
Exception in thread "main" java.io.EOFException: Chunked stream has ended unexpectedly: no chunk size
at io.ktor.http.cio.ChunkedTransferEncodingKt.decodeChunked(ChunkedTransferEncoding.kt:77)
at io.ktor.http.cio.ChunkedTransferEncodingKt$decodeChunked$3.invokeSuspend(ChunkedTransferEncoding.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
The error happens randomly, and it only seems to affect big (1MB+) requests... And here's the rabbit hole that I went down to track the bug and figure out a solution.
Java's ScheduledExecutorService
has a nifty scheduleAtFixedRate
API, which allows you to schedule a Runnable
to be executed in a recurring manner.
Mimicking scheduleAtFixedRate
seems easy, after all, isn't it just a while (true)
loop that invokes your task every once in a while?
GlobalScope.launch {
while (true) {
println("Hello World!! Loritta is so cute :3")
delay(5_000)
}
}
And it seems to work fine, it does print Hello World!! Loritta is so cute :3
every 5s! And you may be wondering: What's wrong with it?
This content is not available in your language... So if you don't understand the language... well, at least you can appreciate the pictures of the post, right?
No /r/brdev, /u/sock_templar compartilhou um endpoint dos Correios que permite você rastrear pacotes dos Correios.
curl https://proxyapp.correios.com.br/v1/sro-rastro/CodigoDeRastreioAqui
Ela mostra os eventos sobre o pacote, parecido com os eventos que você recebe ao rastrear um pacote pelo website dos Correios, e inclusive esse endpoint é usado em várias libraries que existem pela internet.
Mas sabia que existe outro endpoint de rastreio dos Correios, que mostra mais informações sobre o pacote sendo rastreado, como também permite você rastrear vários pacotes em um único request?
Trying to figure out how to list files from a Java Resources folder is hard, there are tons of solutions on StackOverflow, however most of them are weird hacks and they only work when executing your app via your IDE, or when executing your app via the command line, not both.
Joop Eggen's answer is awesome, however it can only do one of two things:
So here's an example (Kotlin, but it should be easy to migrate it to Java) that allows you to have both: Reading the resources content when running from a IDE or via the command line!
val uri = MainApp::class.java.getResource("/locales/").toURI()
val dirPath = try {
Paths.get(uri)
} catch (e: FileSystemNotFoundException) {
// If this is thrown, then it means that we are running the JAR directly (example: not from an IDE)
val env = mutableMapOf<String, String>()
FileSystems.newFileSystem(uri, env).getPath("/locales/")
}
Files.list(dirPath).forEach {
println(it.fileName)
if (it.fileName.toString().endsWith("txt")) {
println("Result:")
println(Files.readString(it))
}
}
StackOverflow Post: https://stackoverflow.com/a/67839914/7271796
I needed to reload my network interface on the machine where my PostgreSQL database is hosted and, after doing that, my thread got forever blocked on the getNotifications(...)
call.
"Loritta PostgreSQL Notification Listener" #261 daemon prio=5 os_prio=0 cpu=48.89ms elapsed=62372.91s tid=0x00007f45f806a460 nid=0xf08b5 runnable [0x00007f45d6dfc000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Net.poll([email protected]/Native Method)
at sun.nio.ch.NioSocketImpl.park([email protected]/NioSocketImpl.java:181)
at sun.nio.ch.NioSocketImpl.timedRead([email protected]/NioSocketImpl.java:285)
at sun.nio.ch.NioSocketImpl.implRead([email protected]/NioSocketImpl.java:309)
at sun.nio.ch.NioSocketImpl.read([email protected]/NioSocketImpl.java:350)
at sun.nio.ch.NioSocketImpl$1.read([email protected]/NioSocketImpl.java:803)
at java.net.Socket$SocketInputStream.read([email protected]/Socket.java:966)
at sun.security.ssl.SSLSocketInputRecord.read([email protected]/SSLSocketInputRecord.java:478)
at sun.security.ssl.SSLSocketInputRecord.readHeader([email protected]/SSLSocketInputRecord.java:472)
at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket([email protected]/SSLSocketInputRecord.java:70)
at sun.security.ssl.SSLSocketImpl.readApplicationRecord([email protected]/SSLSocketImpl.java:1455)
at sun.security.ssl.SSLSocketImpl$AppInputStream.read([email protected]/SSLSocketImpl.java:1059)
at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:161)
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:128)
at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:113)
at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)
at org.postgresql.core.PGStream.receiveChar(PGStream.java:453)
at org.postgresql.core.v3.QueryExecutorImpl.processNotifies(QueryExecutorImpl.java:789)
- locked <0x0000000621293410> (a org.postgresql.core.v3.QueryExecutorImpl)
at org.postgresql.jdbc.PgConnection.getNotifications(PgConnection.java:1107)
at net.perfectdreams.loritta.cinnamon.pudding.utils.PostgreSQLNotificationListener.run(PostgreSQLNotificationListener.kt:29)
at java.lang.Thread.run([email protected]/Thread.java:833)
So I went out and tried figuring out if this could be reproduced, and found out that someone had already reported this issue, but it was closed due to "lack of feedback". Anyhow, here's my investigations and explanations to anyone else wondering why their PostgreSQL getNotifications
call is not receiving new notifications, even tho it is blocked on the getNotifications
call!
Exposed's exposed-java-time
(and exposed-kotlin-datetime
) module has an issue: In PostgreSQL it uses TIMESTAMP WITHOUT TIME ZONE
and always saves the timestamp using the system's current time zone (ZoneId.systemDefault()
).
So, if you are running your application in two different time zones, the inserted result of Instant.now()
will be different, even if the code was executed at the same nanosecond!
I got bit by this bug in Loritta, where the legacy application was using the America/Sao_Paulo
time zone while the newer slash commands web server was using UTC
. This caused inconsistencies in the database where transactions inserted by the legacy application were older than transactions inserted by the web server!
While you can workaround the issue by using TimeZone.setDefault(TimeZone.getTimeZone("UTC"))
in your code, this isn't a great solution. Besides, it is recommended that you use TIMESTAMP WITH TIME ZONE
, even if you are using a java.time.Instant
!
Thankfully Exposed is very extendable, allowing you to support features that it doesn't support out of the box! So I submitted my TIMESTAMP WITH TIME ZONE
implementation to my ExposedPowerUtils repository, with other nifty Exposed utilities and extensions.
object ActionLog : LongIdTable() {
// Instead of using timestamp, use "timestampWithTimeZone"
// This returns a "Instant"
val timestamp = timestampWithTimeZone("timestamp")
}
Check out the ExposedPowerUtils repository, include the postgres-java-time
in your project, and have fun! Or if you prefer, just copy the JavaTimestampWithTimeZoneColumnType
file to your project.
Keep in mind that Exposed won't change the column type automatically if the table is already created, you can change it by ALTER TABLE sonhostransactionslog ALTER COLUMN timestamp TYPE TIMESTAMP WITH TIME ZONE;
. In my experience, if your current TIMESTAMP WITHOUT TIME ZONE
are in UTC, you shouldn't have any issues when migrating to a TIMESTAMP WITH TIME ZONE
!