Skip to content

Commit

Permalink
Keep an fsi process ready for when we need it
Browse files Browse the repository at this point in the history
  • Loading branch information
1tgr committed Nov 17, 2012
1 parent 95125ed commit efc2d57
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 30 deletions.
8 changes: 6 additions & 2 deletions Tim.TryFSharp.Service/app.fs
Expand Up @@ -14,6 +14,7 @@ type App =
BaseUri : Uri
OwnSessions : Map<string, string * FsiProcess>
SlowStop : bool
NextInteractiveProcess : Process
}

type Command =
Expand Down Expand Up @@ -101,15 +102,18 @@ module App =
Recycle = fun () -> inbox.Post (Recycle id)
}

let proc = new FsiProcess(info)
let proc = new FsiProcess(info, app.NextInteractiveProcess)
let app = { app with NextInteractiveProcess = FsiProcess.Start() }

let session =
{ session with
FsiPid = Some (int64 proc.Process.Id)
Started = Some DateTime.Now
}

let rev = TryFSharpDB.putSession app.BaseUri id session
{ app with OwnSessions = Map.add id (Option.get rev.Rev, proc) app.OwnSessions }, OwnSession proc
let app = { app with OwnSessions = Map.add id (Option.get rev.Rev, proc) app.OwnSessions }
app, OwnSession proc
with ex ->
CouchDB.deleteDocument app.BaseUri id (Option.get rev.Rev)
app, ProcessFailed ex
Expand Down
49 changes: 25 additions & 24 deletions Tim.TryFSharp.Service/fsiProcess.fs
Expand Up @@ -17,7 +17,7 @@ type FsiProcessInfo =
Recycle : unit -> unit
}

type FsiProcess(info : FsiProcessInfo) =
type FsiProcess(info : FsiProcessInfo, proc : Process) =
let path = Path.Combine(Path.GetTempPath(), info.Name)

let initTexts =
Expand All @@ -30,23 +30,6 @@ type FsiProcess(info : FsiProcessInfo) =

Path.ChangeExtension(name, ".fsx"), text |]

let proc =
let fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tim.TryFSharp.Interactive.exe")

let fileName, arguments =
match Type.GetType("Mono.Runtime") with
| null -> fileName, [ ]
| _ -> "mono", [ fileName ]

new Process(
StartInfo = ProcessStartInfo(
FileName = fileName,
WorkingDirectory = path,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false))

let syncRoot = obj()
let buffer = ResizeArray<string>()

Expand Down Expand Up @@ -84,18 +67,16 @@ type FsiProcess(info : FsiProcessInfo) =
proc.ErrorDataReceived.Add post

ignore (Directory.CreateDirectory path)
for name, text in initTexts do
File.WriteAllText(Path.Combine(path, name), text)

ignore (proc.Start())

let arguments =
[|
yield sprintf "-I:%s" (Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "assemblies"))
yield! info.Arguments

for name, _ in initTexts do
yield sprintf "--use:%s" name
for name, text in initTexts do
let filename = Path.Combine(path, name)
File.WriteAllText(filename, text)
yield sprintf "--use:%s" filename
|]

let argumentsJson =
Expand All @@ -110,6 +91,26 @@ type FsiProcess(info : FsiProcessInfo) =
proc.BeginErrorReadLine()
proc.BeginOutputReadLine()

static member Start() : Process =
let fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tim.TryFSharp.Interactive.exe")

let fileName, arguments =
match Type.GetType("Mono.Runtime") with
| null -> fileName, [ ]
| _ -> "mono", [ fileName ]

let proc =
new Process(
StartInfo = ProcessStartInfo(
FileName = fileName,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = false))

ignore (proc.Start())
proc

member this.Process = proc

interface IDisposable with
Expand Down
1 change: 1 addition & 0 deletions Tim.TryFSharp.Service/service.fs
Expand Up @@ -183,6 +183,7 @@ type ServiceState =
BaseUri = config.BaseUri
OwnSessions = Map.empty
SlowStop = false
NextInteractiveProcess = FsiProcess.Start()
}

MailboxProcessor.Start(App.run app, cts.Token)
Expand Down
10 changes: 6 additions & 4 deletions Tim.TryFSharp.Test/serviceTests.fs
Expand Up @@ -10,7 +10,8 @@ type ServiceTests() =

[<Fact>]
let ``Should start and stop fsi`` () =
use proc = new FsiProcess({ Name = Path.GetRandomFileName(); InitTexts = [| |]; Arguments = [| |]; Print = Console.WriteLine; Recycle = id })
use proc = FsiProcess.Start()
use fsiProc = new FsiProcess({ Name = Path.GetRandomFileName(); InitTexts = [| |]; Arguments = [| |]; Print = Console.WriteLine; Recycle = id }, proc)
()

[<Fact>]
Expand All @@ -25,8 +26,9 @@ type ServiceTests() =
ignore (gotMessage.Set())

let success =
using (new FsiProcess({ Name = Path.GetRandomFileName(); InitTexts = [| |]; Arguments = [| |]; Print = print; Recycle = id })) <| fun fsi ->
fsi.Process.StandardInput.WriteLine("printfn \"{0}\";;", message)
gotMessage.WaitOne(TimeSpan.FromSeconds(30.0))
use proc = FsiProcess.Start()
use fsiProc = new FsiProcess({ Name = Path.GetRandomFileName(); InitTexts = [| |]; Arguments = [| |]; Print = print; Recycle = id }, proc)
fsiProc.Process.StandardInput.WriteLine("printfn \"{0}\";;", message)
gotMessage.WaitOne(TimeSpan.FromSeconds(30.0))

Assert.True(success, sprintf "Should have '%s' in: %A" message (lines.ToArray()))

0 comments on commit efc2d57

Please sign in to comment.