Fix: DNS TTL uses seconds while caching usese millis (#25848)
* Fix: DNS TTL uses seconds while caching uses millis * Consistently rename ttl vals in companion objects. Add mima filters. * Rename fields to ttlInZzzz format
This commit is contained in:
parent
87a033efff
commit
48cf769ee7
4 changed files with 41 additions and 33 deletions
|
|
@ -0,0 +1,8 @@
|
||||||
|
# #25848 - TTL seconds used when TTL milliseconds expected
|
||||||
|
# Change of a field name with ApiMayChange
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.UnknownRecord.ttl")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.ARecord.ttl")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.CNameRecord.ttl")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.AAAARecord.ttl")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.ResourceRecord.ttl")
|
||||||
|
ProblemFilters.exclude[DirectMissingMethodProblem]("akka.io.dns.SRVRecord.ttl")
|
||||||
|
|
@ -14,7 +14,7 @@ import akka.util.{ ByteIterator, ByteString, ByteStringBuilder }
|
||||||
import scala.annotation.switch
|
import scala.annotation.switch
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
sealed abstract class ResourceRecord(val name: String, val ttl: Int, val recType: Short, val recClass: Short)
|
sealed abstract class ResourceRecord(val name: String, val ttlInSeconds: Int, val recType: Short, val recClass: Short)
|
||||||
extends NoSerializationVerificationNeeded {
|
extends NoSerializationVerificationNeeded {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -29,8 +29,8 @@ sealed abstract class ResourceRecord(val name: String, val ttl: Int, val recType
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
final case class ARecord(override val name: String, override val ttl: Int,
|
final case class ARecord(override val name: String, override val ttlInSeconds: Int,
|
||||||
ip: InetAddress) extends ResourceRecord(name, ttl, RecordType.A.code, RecordClass.IN.code) {
|
ip: InetAddress) extends ResourceRecord(name, ttlInSeconds, RecordType.A.code, RecordClass.IN.code) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
|
|
@ -49,16 +49,16 @@ final case class ARecord(override val name: String, override val ttl: Int,
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
private[dns] object ARecord {
|
private[dns] object ARecord {
|
||||||
def parseBody(name: String, ttl: Int, length: Short, it: ByteIterator): ARecord = {
|
def parseBody(name: String, ttlInSeconds: Int, length: Short, it: ByteIterator): ARecord = {
|
||||||
val addr = Array.ofDim[Byte](4)
|
val addr = Array.ofDim[Byte](4)
|
||||||
it.getBytes(addr)
|
it.getBytes(addr)
|
||||||
ARecord(name, ttl, InetAddress.getByAddress(addr).asInstanceOf[Inet4Address])
|
ARecord(name, ttlInSeconds, InetAddress.getByAddress(addr).asInstanceOf[Inet4Address])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
final case class AAAARecord(override val name: String, override val ttl: Int,
|
final case class AAAARecord(override val name: String, override val ttlInSeconds: Int,
|
||||||
ip: Inet6Address) extends ResourceRecord(name, ttl, RecordType.AAAA.code, RecordClass.IN.code) {
|
ip: Inet6Address) extends ResourceRecord(name, ttlInSeconds, RecordType.AAAA.code, RecordClass.IN.code) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
|
|
@ -82,16 +82,16 @@ private[dns] object AAAARecord {
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
def parseBody(name: String, ttl: Int, length: Short, it: ByteIterator): AAAARecord = {
|
def parseBody(name: String, ttlInSeconds: Int, length: Short, it: ByteIterator): AAAARecord = {
|
||||||
val addr = Array.ofDim[Byte](16)
|
val addr = Array.ofDim[Byte](16)
|
||||||
it.getBytes(addr)
|
it.getBytes(addr)
|
||||||
AAAARecord(name, ttl, InetAddress.getByAddress(addr).asInstanceOf[Inet6Address])
|
AAAARecord(name, ttlInSeconds, InetAddress.getByAddress(addr).asInstanceOf[Inet6Address])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
final case class CNameRecord(override val name: String, override val ttl: Int,
|
final case class CNameRecord(override val name: String, override val ttlInSeconds: Int,
|
||||||
canonicalName: String) extends ResourceRecord(name, ttl, RecordType.CNAME.code, RecordClass.IN.code) {
|
canonicalName: String) extends ResourceRecord(name, ttlInSeconds, RecordType.CNAME.code, RecordClass.IN.code) {
|
||||||
/**
|
/**
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
|
|
@ -109,14 +109,14 @@ private[dns] object CNameRecord {
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
def parseBody(name: String, ttl: Int, length: Short, it: ByteIterator, msg: ByteString): CNameRecord = {
|
def parseBody(name: String, ttlInSeconds: Int, length: Short, it: ByteIterator, msg: ByteString): CNameRecord = {
|
||||||
CNameRecord(name, ttl, DomainName.parse(it, msg))
|
CNameRecord(name, ttlInSeconds, DomainName.parse(it, msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
final case class SRVRecord(override val name: String, override val ttl: Int,
|
final case class SRVRecord(override val name: String, override val ttlInSeconds: Int,
|
||||||
priority: Int, weight: Int, port: Int, target: String) extends ResourceRecord(name, ttl, RecordType.SRV.code, RecordClass.IN.code) {
|
priority: Int, weight: Int, port: Int, target: String) extends ResourceRecord(name, ttlInSeconds, RecordType.SRV.code, RecordClass.IN.code) {
|
||||||
/**
|
/**
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
|
|
@ -139,18 +139,18 @@ private[dns] object SRVRecord {
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
def parseBody(name: String, ttl: Int, length: Short, it: ByteIterator, msg: ByteString): SRVRecord = {
|
def parseBody(name: String, ttlInSeconds: Int, length: Short, it: ByteIterator, msg: ByteString): SRVRecord = {
|
||||||
val priority = it.getShort
|
val priority = it.getShort
|
||||||
val weight = it.getShort
|
val weight = it.getShort
|
||||||
val port = it.getShort
|
val port = it.getShort
|
||||||
SRVRecord(name, ttl, priority, weight, port, DomainName.parse(it, msg))
|
SRVRecord(name, ttlInSeconds, priority, weight, port, DomainName.parse(it, msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiMayChange
|
@ApiMayChange
|
||||||
final case class UnknownRecord(override val name: String, override val ttl: Int,
|
final case class UnknownRecord(override val name: String, override val ttlInSeconds: Int,
|
||||||
override val recType: Short, override val recClass: Short,
|
override val recType: Short, override val recClass: Short,
|
||||||
data: ByteString) extends ResourceRecord(name, ttl, recType, recClass) {
|
data: ByteString) extends ResourceRecord(name, ttlInSeconds, recType, recClass) {
|
||||||
/**
|
/**
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
|
|
@ -171,8 +171,8 @@ private[dns] object UnknownRecord {
|
||||||
* INTERNAL API
|
* INTERNAL API
|
||||||
*/
|
*/
|
||||||
@InternalApi
|
@InternalApi
|
||||||
def parseBody(name: String, ttl: Int, recType: Short, recClass: Short, length: Short, it: ByteIterator): UnknownRecord =
|
def parseBody(name: String, ttlInSeconds: Int, recType: Short, recClass: Short, length: Short, it: ByteIterator): UnknownRecord =
|
||||||
UnknownRecord(name, ttl, recType, recClass, it.toByteString)
|
UnknownRecord(name, ttlInSeconds, recType, recClass, it.toByteString)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,10 @@ import scala.annotation.tailrec
|
||||||
}
|
}
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
private[io] final def put(key: (String, QueryType), records: Answer, ttlMillis: Long): Unit = {
|
private[io] final def put(key: (String, QueryType), records: Answer, ttlInMillis: Long): Unit = {
|
||||||
val c = cache.get()
|
val c = cache.get()
|
||||||
if (!cache.compareAndSet(c, c.put(key, records, ttlMillis)))
|
if (!cache.compareAndSet(c, c.put(key, records, ttlInMillis)))
|
||||||
put(key, records, ttlMillis)
|
put(key, records, ttlInMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
@tailrec
|
@tailrec
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,13 @@ private[io] final class AsyncDnsResolver(
|
||||||
ipv4Recs.flatMap(ipv4Records ⇒ {
|
ipv4Recs.flatMap(ipv4Records ⇒ {
|
||||||
// TODO, do we want config to specify a max for this?
|
// TODO, do we want config to specify a max for this?
|
||||||
if (ipv4Records.rrs.nonEmpty) {
|
if (ipv4Records.rrs.nonEmpty) {
|
||||||
val minTtl4 = ipv4Records.rrs.minBy(_.ttl).ttl
|
val minTtl4 = ipv4Records.rrs.minBy(_.ttlInSeconds).ttlInSeconds
|
||||||
cache.put((name, Ipv4Type), ipv4Records, minTtl4)
|
cache.put((name, Ipv4Type), ipv4Records, minTtl4 * 1000)
|
||||||
}
|
}
|
||||||
ipv6Recs.map(ipv6Records ⇒ {
|
ipv6Recs.map(ipv6Records ⇒ {
|
||||||
if (ipv6Records.rrs.nonEmpty) {
|
if (ipv6Records.rrs.nonEmpty) {
|
||||||
val minTtl6 = ipv6Records.rrs.minBy(_.ttl).ttl
|
val minTtl6 = ipv6Records.rrs.minBy(_.ttlInSeconds).ttlInSeconds
|
||||||
cache.put((name, Ipv6Type), ipv6Records, minTtl6)
|
cache.put((name, Ipv6Type), ipv6Records, minTtl6 * 1000)
|
||||||
}
|
}
|
||||||
ipv4Records.rrs ++ ipv6Records.rrs
|
ipv4Records.rrs ++ ipv6Records.rrs
|
||||||
}).map(recs ⇒ DnsProtocol.Resolved(name, recs))
|
}).map(recs ⇒ DnsProtocol.Resolved(name, recs))
|
||||||
|
|
@ -134,12 +134,12 @@ private[io] final class AsyncDnsResolver(
|
||||||
Future.successful(DnsProtocol.Resolved(name, r.rrs, r.additionalRecs))
|
Future.successful(DnsProtocol.Resolved(name, r.rrs, r.additionalRecs))
|
||||||
case None ⇒
|
case None ⇒
|
||||||
sendQuestion(resolver, SrvQuestion(nextId(), caseFoldedName))
|
sendQuestion(resolver, SrvQuestion(nextId(), caseFoldedName))
|
||||||
.map(r ⇒ {
|
.map(answer ⇒ {
|
||||||
if (r.rrs.nonEmpty) {
|
if (answer.rrs.nonEmpty) {
|
||||||
val minTtl = r.rrs.minBy(_.ttl).ttl
|
val minttlInSeconds = answer.rrs.minBy(_.ttlInSeconds).ttlInSeconds
|
||||||
cache.put((name, SrvType), r, minTtl)
|
cache.put((name, SrvType), answer, minttlInSeconds * 1000) // cache uses ttl in millis
|
||||||
}
|
}
|
||||||
DnsProtocol.Resolved(name, r.rrs, r.additionalRecs)
|
DnsProtocol.Resolved(name, answer.rrs, answer.additionalRecs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue