Add polling

This commit is contained in:
Lars Westermann 2019-06-11 15:10:51 +02:00
parent 927649bba6
commit ce4e4635e3
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
6 changed files with 59 additions and 15 deletions

View file

@ -18,7 +18,15 @@ data class Message(
val type: MessageType,
val repository: RepositoryType,
val id: Long
)
) {
companion object {
val empty = Message(
MessageType.UPDATE,
RepositoryType.ANNOUNCEMENT,
0L
)
}
}
enum class MessageType {
CREATE, UPDATE, DELETE

View file

@ -13,7 +13,7 @@ import org.w3c.xhr.XMLHttpRequest
import kotlin.browser.document
import kotlin.browser.window
class WebSocketClient {
class PushServiceClient {
private val prefix = js("prefix")
private val url = "$prefix/api/updates"
private val body = document.body ?: createHtmlView()

View file

@ -12,7 +12,7 @@ import de.westermann.kwebview.components.init
import kotlin.browser.document
fun main() = init {
WebSocketClient()
PushServiceClient()
if (document.getElementsByClassName("calendar").length > 0) {
initCalendar()

View file

@ -21,15 +21,15 @@ object AnnouncementRepository {
suspend fun getAnnouncement(): String {
val json = repositoryGet("$prefix/api/announcement") ?: return ""
return parser.parse(json, String.serializer())
return json as String
}
suspend fun setAnnouncement(value: String){
return repositoryPost("$prefix/api/announcement", Serialization.stringify(String.serializer(), value))
return repositoryPost("$prefix/api/announcement", value)
?: throw IllegalStateException("Cannot set announcement!")
}
val handler = object : MessageHandler(RepositoryType.ROOM) {
val handler = object : MessageHandler(RepositoryType.ANNOUNCEMENT) {
override fun onCreate(id: Long) {}

View file

@ -18,4 +18,4 @@ fun initAnnouncement() {
span.textContent = text
}
}
}
}

View file

@ -14,7 +14,9 @@ import io.ktor.routing.get
object PushService {
var leastValidTimestamp = System.currentTimeMillis()
private var leastValidTimestamp = System.currentTimeMillis()
private val messages: MutableList<Pair<Long, Message>> = mutableListOf()
/**
* Save the message with the current timestamp
@ -22,6 +24,21 @@ object PushService {
fun notify(type: MessageType, repository: RepositoryType, id: Long) {
val timestamp = System.currentTimeMillis()
val message = Message(type, repository, id)
synchronized(messages) {
messages += Pair(timestamp, message)
}
}
private fun getIndexOfTimestamp(timestamp: Long): Int {
val index = messages.binarySearch(Pair(timestamp, Message.empty), compareBy { it.first })
val i = if (index < 0) {
-index - 1
} else {
index
}
return if (i < 0) 0 else i
}
/**
@ -29,12 +46,25 @@ object PushService {
* The return Box has the current timestamp. If the leastValidTimestamp is less then the current timestamp set the
* valid flag to false and return an empty message list.
*/
fun getMessages(timestamp: Long?): MessageBox {
return MessageBox(
System.currentTimeMillis(),
timestamp != null && timestamp > leastValidTimestamp,
emptyList()
)
fun getMessages(timestamp: Long): MessageBox {
return if (timestamp < leastValidTimestamp) {
MessageBox(
System.currentTimeMillis(),
false,
emptyList()
)
} else {
val m = synchronized(messages) {
val index = getIndexOfTimestamp(timestamp)
messages.drop(index)
}
MessageBox(
System.currentTimeMillis(),
true,
m.map { it.second }
)
}
}
/**
@ -42,13 +72,19 @@ object PushService {
*/
fun gc(timestamp: Long) {
leastValidTimestamp = timestamp
synchronized(messages) {
messages.removeIf {
it.first < timestamp
}
}
}
}
fun Route.pushService() {
get("/api/updates") {
try {
val timestamp = call.request.queryParameters["timestamp"]?.toLongOrNull()
val timestamp = call.request.queryParameters["timestamp"]?.toLongOrNull() ?: 0
val messageBox = PushService.getMessages(timestamp)