-
Notifications
You must be signed in to change notification settings - Fork 326
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement `GET / _idle` request
- Loading branch information
Showing
12 changed files
with
411 additions
and
5 deletions.
There are no files selected for viewing
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
--- | ||
layout: developer-doc | ||
title: Language Server HTTP Endpoints | ||
category: language-server | ||
tags: [language-server, protocol, specification] | ||
order: 6 | ||
--- | ||
|
||
# HTTP Endpoints | ||
|
||
Language server exposes a number of HTTP endpoints on the same socket as the | ||
JSONRPC protocol. | ||
|
||
<!-- MarkdownTOC levels="2" autolink="true" indent=" " --> | ||
|
||
- [`/_health`](#---health-) | ||
- [`/_health/readiness`](#---health-readiness-) | ||
- [`/_health/liveness`](#---health-liveness-) | ||
- [`/_idle`](#---idle-) | ||
|
||
<!-- /MarkdownTOC --> | ||
|
||
## `/_health` | ||
|
||
HTTP endpoint that provides basic health checking capabilities. | ||
|
||
### `GET | HEAD` | ||
|
||
Returns `200 OK` when the server is started and `500 Internal Server Error` | ||
otherwise. | ||
|
||
#### Request | ||
|
||
```text | ||
> GET /_health HTTP/1.1 | ||
> Host: localhost:63597 | ||
> User-Agent: curl/7.77.0 | ||
> Accept: */* | ||
``` | ||
|
||
#### Response | ||
|
||
```text | ||
< HTTP/1.1 200 OK | ||
< Server: akka-http/10.2.0-RC1 | ||
< Date: Fri, 09 Jul 2021 15:16:16 GMT | ||
< Content-Type: text/plain; charset=UTF-8 | ||
< Content-Length: 2 | ||
< | ||
OK | ||
``` | ||
|
||
## `/_health/readiness` | ||
|
||
The server readiness probe. | ||
|
||
### `GET | HEAD` | ||
|
||
Returns `200 OK` when the server is initialized and `500 Internal Server Error` | ||
otherwise. | ||
|
||
#### Request | ||
|
||
```text | ||
> GET /_health/readiness HTTP/1.1 | ||
> Host: localhost:63597 | ||
> User-Agent: curl/7.77.0 | ||
> Accept: */* | ||
``` | ||
|
||
#### Response | ||
|
||
```text | ||
< HTTP/1.1 200 OK | ||
< Server: akka-http/10.2.0-RC1 | ||
< Date: Fri, 09 Jul 2021 15:30:53 GMT | ||
< Content-Type: text/plain; charset=UTF-8 | ||
< Content-Length: 2 | ||
< | ||
OK | ||
``` | ||
|
||
## `/_health/liveness` | ||
|
||
The server liveness probe. | ||
|
||
### `GET | HEAD` | ||
|
||
Checks if all the server subsystems are functioning and returns `200 OK` or | ||
`500 Internal Server Error` otherwise. | ||
|
||
#### Request | ||
|
||
```text | ||
> GET /_health/liveness HTTP/1.1 | ||
> Host: localhost:60339 | ||
> User-Agent: curl/7.77.0 | ||
> Accept: */* | ||
``` | ||
|
||
#### Response | ||
|
||
```text | ||
< HTTP/1.1 200 OK | ||
< Server: akka-http/10.2.0-RC1 | ||
< Date: Fri, 09 Jul 2021 15:35:43 GMT | ||
< Content-Type: text/plain; charset=UTF-8 | ||
< Content-Length: 2 | ||
< | ||
OK | ||
``` | ||
|
||
## `/_idle` | ||
|
||
The server idleness probe. | ||
|
||
### `GET` | ||
|
||
Return the amount of time the language server is idle. | ||
|
||
#### Request | ||
|
||
```text | ||
> GET /_idle HTTP/1.1 | ||
> Host: localhost:60339 | ||
> User-Agent: curl/7.77.0 | ||
> Accept: */* | ||
``` | ||
|
||
#### Response | ||
|
||
```text | ||
< HTTP/1.1 200 OK | ||
< Server: akka-http/10.2.0-RC1 | ||
< Date: Fri, 09 Jul 2021 15:44:51 GMT | ||
< Content-Type: application/json | ||
< Content-Length: 21 | ||
< | ||
{"idle_time_sec":58} | ||
``` |
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
64 changes: 64 additions & 0 deletions
64
.../language-server/src/main/scala/org/enso/languageserver/monitoring/IdlenessEndpoint.scala
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package org.enso.languageserver.monitoring | ||
|
||
import akka.actor.ActorRef | ||
import akka.http.scaladsl.model.{ | ||
ContentTypes, | ||
HttpEntity, | ||
MessageEntity, | ||
StatusCodes | ||
} | ||
import akka.http.scaladsl.server.Directives._ | ||
import akka.http.scaladsl.server.Route | ||
import akka.pattern.ask | ||
import akka.util.Timeout | ||
import com.typesafe.scalalogging.LazyLogging | ||
import org.enso.jsonrpc._ | ||
|
||
import scala.concurrent.duration._ | ||
import scala.util.{Failure, Success} | ||
|
||
/** HTTP endpoint that provides idleness capabilities. | ||
* | ||
* @param idlenessMonitor an actor monitoring the server idle time | ||
*/ | ||
class IdlenessEndpoint( | ||
idlenessMonitor: ActorRef | ||
) extends Endpoint | ||
with LazyLogging { | ||
|
||
implicit private val timeout: Timeout = Timeout(10.seconds) | ||
|
||
/** @inheritdoc */ | ||
override def route: Route = | ||
idlenessProbe | ||
|
||
private val idlenessProbe = | ||
path("_idle") { | ||
get { | ||
checkIdleness() | ||
} | ||
} | ||
|
||
private def checkIdleness(): Route = { | ||
val future = idlenessMonitor ? MonitoringProtocol.GetIdleTime | ||
|
||
onComplete(future) { | ||
case Failure(_) => | ||
complete(StatusCodes.InternalServerError) | ||
case Success(r: MonitoringProtocol.IdleTime) => | ||
complete(IdlenessEndpoint.toHttpEntity(r)) | ||
case Success(r) => | ||
logger.error("Unexpected response from idleness monitor: [{}]", r) | ||
complete(StatusCodes.InternalServerError) | ||
} | ||
} | ||
} | ||
|
||
object IdlenessEndpoint { | ||
|
||
private def toJsonText(t: MonitoringProtocol.IdleTime): String = | ||
s"""{"idle_time_sec":${t.idleTimeSeconds}}""" | ||
|
||
def toHttpEntity(t: MonitoringProtocol.IdleTime): MessageEntity = | ||
HttpEntity(ContentTypes.`application/json`, toJsonText(t)) | ||
} |
35 changes: 35 additions & 0 deletions
35
...e/language-server/src/main/scala/org/enso/languageserver/monitoring/IdlenessMonitor.scala
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.enso.languageserver.monitoring | ||
|
||
import java.time.{Clock, Duration, Instant} | ||
|
||
import akka.actor.{Actor, Props} | ||
import org.enso.languageserver.util.UnhandledLogging | ||
|
||
/** An actor that monitors the server time spent idle. | ||
* | ||
* @param clock the system clock | ||
*/ | ||
class IdlenessMonitor(clock: Clock) extends Actor with UnhandledLogging { | ||
|
||
override def receive: Receive = initialized(clock.instant()) | ||
|
||
private def initialized(lastActiveTime: Instant): Receive = { | ||
case MonitoringProtocol.ResetIdleTime => | ||
context.become(initialized(clock.instant())) | ||
|
||
case MonitoringProtocol.GetIdleTime => | ||
val idleTime = Duration.between(lastActiveTime, clock.instant()) | ||
sender() ! MonitoringProtocol.IdleTime(idleTime.toSeconds) | ||
} | ||
|
||
} | ||
|
||
object IdlenessMonitor { | ||
|
||
/** Creates a configuration object used to create an idleness monitor. | ||
* | ||
* @return a configuration object | ||
*/ | ||
def props(clock: Clock): Props = Props(new IdlenessMonitor(clock)) | ||
|
||
} |
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
Oops, something went wrong.