mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 00:11:45 +03:00
Allow file/read to return the contents of a collaborative buffer (#9994)
part of #9960 Changelog: - feat: file/read return contents of a collaborative buffer if they are available and fallback to reading the file from disk
This commit is contained in:
parent
1991aab19d
commit
643b66d0b7
@ -538,7 +538,7 @@ class JsonConnectionController(
|
||||
WriteFile -> file.WriteTextualFileHandler
|
||||
.props(requestTimeout, fileManager),
|
||||
ReadFile -> file.ReadTextualFileHandler
|
||||
.props(requestTimeout, fileManager),
|
||||
.props(requestTimeout, bufferRegistry, fileManager),
|
||||
CreateFile -> file.CreateFileHandler.props(requestTimeout, fileManager),
|
||||
DeleteFile -> file.DeleteFileHandler.props(requestTimeout, fileManager),
|
||||
CopyFile -> file.CopyFileHandler.props(requestTimeout, fileManager),
|
||||
|
@ -9,6 +9,10 @@ import org.enso.languageserver.filemanager.{
|
||||
}
|
||||
import org.enso.languageserver.filemanager.FileManagerApi.ReadFile
|
||||
import org.enso.languageserver.requesthandler.RequestTimeout
|
||||
import org.enso.languageserver.text.TextProtocol.{
|
||||
ReadCollaborativeBuffer,
|
||||
ReadCollaborativeBufferResult
|
||||
}
|
||||
import org.enso.languageserver.util.UnhandledLogging
|
||||
import org.enso.logger.masking.MaskedString
|
||||
|
||||
@ -16,6 +20,7 @@ import scala.concurrent.duration.FiniteDuration
|
||||
|
||||
class ReadTextualFileHandler(
|
||||
requestTimeout: FiniteDuration,
|
||||
bufferRegistry: ActorRef,
|
||||
fileManager: ActorRef
|
||||
) extends Actor
|
||||
with LazyLogging
|
||||
@ -27,10 +32,53 @@ class ReadTextualFileHandler(
|
||||
|
||||
private def requestStage: Receive = {
|
||||
case Request(ReadFile, id, params: ReadFile.Params) =>
|
||||
bufferRegistry ! ReadCollaborativeBuffer(params.path)
|
||||
val cancellable = context.system.scheduler
|
||||
.scheduleOnce(requestTimeout, self, RequestTimeout)
|
||||
context.become(requestBufferStage(id, sender(), cancellable, params))
|
||||
}
|
||||
|
||||
private def requestBufferStage(
|
||||
id: Id,
|
||||
replyTo: ActorRef,
|
||||
cancellable: Cancellable,
|
||||
params: ReadFile.Params
|
||||
): Receive = {
|
||||
case Status.Failure(ex) =>
|
||||
logger.error(
|
||||
"Failure during [{}] operation: {}",
|
||||
ReadFile,
|
||||
MaskedString(ex.getMessage)
|
||||
)
|
||||
replyTo ! ResponseError(Some(id), Errors.ServiceError)
|
||||
cancellable.cancel()
|
||||
context.stop(self)
|
||||
|
||||
case RequestTimeout =>
|
||||
logger.warn(
|
||||
"Read collaborative buffer timed out. " +
|
||||
"Falling back to reading file contents."
|
||||
)
|
||||
fileManager ! FileManagerProtocol.ReadFile(params.path)
|
||||
val cancellable = context.system.scheduler
|
||||
.scheduleOnce(requestTimeout, self, RequestTimeout)
|
||||
context.become(responseStage(id, sender(), cancellable))
|
||||
context.become(responseStage(id, replyTo, cancellable))
|
||||
|
||||
case ReadCollaborativeBufferResult(None) =>
|
||||
cancellable.cancel()
|
||||
fileManager ! FileManagerProtocol.ReadFile(params.path)
|
||||
val newCancellable = context.system.scheduler
|
||||
.scheduleOnce(requestTimeout, self, RequestTimeout)
|
||||
context.become(responseStage(id, replyTo, newCancellable))
|
||||
|
||||
case ReadCollaborativeBufferResult(Some(buffer)) =>
|
||||
replyTo ! ResponseResult(
|
||||
ReadFile,
|
||||
id,
|
||||
ReadFile.Result(buffer.contents.toString)
|
||||
)
|
||||
cancellable.cancel()
|
||||
context.stop(self)
|
||||
}
|
||||
|
||||
private def responseStage(
|
||||
@ -70,7 +118,11 @@ class ReadTextualFileHandler(
|
||||
|
||||
object ReadTextualFileHandler {
|
||||
|
||||
def props(timeout: FiniteDuration, fileManager: ActorRef): Props =
|
||||
Props(new ReadTextualFileHandler(timeout, fileManager))
|
||||
def props(
|
||||
timeout: FiniteDuration,
|
||||
bufferRegistry: ActorRef,
|
||||
fileManager: ActorRef
|
||||
): Props =
|
||||
Props(new ReadTextualFileHandler(timeout, bufferRegistry, fileManager))
|
||||
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ import org.enso.languageserver.text.TextProtocol.{
|
||||
FileSaved,
|
||||
OpenBuffer,
|
||||
OpenFile,
|
||||
ReadCollaborativeBuffer,
|
||||
ReadCollaborativeBufferResult,
|
||||
SaveFailed,
|
||||
SaveFile
|
||||
}
|
||||
@ -156,6 +158,13 @@ class BufferRegistry(
|
||||
context.become(running(registry + (path -> bufferRef)))
|
||||
}
|
||||
|
||||
case msg @ ReadCollaborativeBuffer(path) =>
|
||||
if (registry.contains(path)) {
|
||||
registry(path).forward(msg)
|
||||
} else {
|
||||
sender() ! ReadCollaborativeBufferResult(None)
|
||||
}
|
||||
|
||||
case Terminated(bufferRef) =>
|
||||
context.become(running(registry.filter(_._2 != bufferRef)))
|
||||
|
||||
|
@ -357,6 +357,9 @@ class CollaborativeBuffer(
|
||||
failure
|
||||
)
|
||||
}
|
||||
|
||||
case ReadCollaborativeBuffer(_) =>
|
||||
sender() ! ReadCollaborativeBufferResult(Some(buffer))
|
||||
}
|
||||
|
||||
private def waitingOnReloadedContent(
|
||||
|
@ -202,4 +202,16 @@ object TextProtocol {
|
||||
/** Signals that the file is modified on disk. */
|
||||
case object SaveFailedFileModifiedOnDisk extends SaveFileResult
|
||||
|
||||
/** Read the contents of a collaborative buffer.
|
||||
*
|
||||
* @param path the file path
|
||||
*/
|
||||
case class ReadCollaborativeBuffer(path: Path)
|
||||
|
||||
/** The data carried by a successful read operation.
|
||||
*
|
||||
* @param buffer file contents
|
||||
*/
|
||||
case class ReadCollaborativeBufferResult(buffer: Option[Buffer])
|
||||
|
||||
}
|
||||
|
@ -408,6 +408,126 @@ class TextOperationsTest
|
||||
}""")
|
||||
}
|
||||
|
||||
"allow file/read to read contents of a buffer" in {
|
||||
val client = getInitialisedWsClient()
|
||||
client.send(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"method": "file/write",
|
||||
"id": 0,
|
||||
"params": {
|
||||
"path": {
|
||||
"rootId": $testContentRootId,
|
||||
"segments": [ "file_read_test.txt" ]
|
||||
},
|
||||
"contents": "123456789"
|
||||
}
|
||||
}
|
||||
""")
|
||||
client.expectJson(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"id": 0,
|
||||
"result": null
|
||||
}
|
||||
""")
|
||||
client.send(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"method": "text/openFile",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"path": {
|
||||
"rootId": $testContentRootId,
|
||||
"segments": [ "file_read_test.txt" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
receiveAndReplyToOpenFile("file_read_test.txt")
|
||||
|
||||
client.expectJson(json"""
|
||||
{
|
||||
"jsonrpc" : "2.0",
|
||||
"id" : 1,
|
||||
"result" : {
|
||||
"writeCapability" : {
|
||||
"method" : "text/canEdit",
|
||||
"registerOptions" : {
|
||||
"path" : {
|
||||
"rootId" : $testContentRootId,
|
||||
"segments" : [
|
||||
"file_read_test.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"content" : "123456789",
|
||||
"currentVersion" : "5795c3d628fd638c9835a4c79a55809f265068c88729a1a3fcdf8522"
|
||||
}
|
||||
}
|
||||
""")
|
||||
|
||||
// apply edit
|
||||
client.send(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"method": "text/applyEdit",
|
||||
"id": 2,
|
||||
"params": {
|
||||
"edit": {
|
||||
"path": {
|
||||
"rootId": $testContentRootId,
|
||||
"segments": [ "file_read_test.txt" ]
|
||||
},
|
||||
"oldVersion": "5795c3d628fd638c9835a4c79a55809f265068c88729a1a3fcdf8522",
|
||||
"newVersion": "ebe55342f9c8b86857402797dd723fb4a2174e0b56d6ace0a6929ec3",
|
||||
"edits": [
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 0, "character": 0 },
|
||||
"end": { "line": 0, "character": 0 }
|
||||
},
|
||||
"text": "bar"
|
||||
},
|
||||
{
|
||||
"range": {
|
||||
"start": { "line": 0, "character": 12 },
|
||||
"end": { "line": 0, "character": 12 }
|
||||
},
|
||||
"text": "foo"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
client.expectJson(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"id": 2,
|
||||
"result": null
|
||||
}
|
||||
""")
|
||||
|
||||
// file/read
|
||||
client.send(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"method": "file/read",
|
||||
"id": 3,
|
||||
"params": {
|
||||
"path": {
|
||||
"rootId": $testContentRootId,
|
||||
"segments": [ "file_read_test.txt" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
client.expectJson(json"""
|
||||
{ "jsonrpc": "2.0",
|
||||
"id": 3,
|
||||
"result": { "contents": "bar123456789foo" }
|
||||
}
|
||||
""")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"text/openFile" must {
|
||||
|
Loading…
Reference in New Issue
Block a user