@@ -16,50 +16,45 @@ import jsonrpclib.internals.MessageDispatcher
1616import jsonrpclib .internals ._
1717
1818import scala .util .Try
19- import _root_ .fs2 .concurrent .SignallingRef
2019
2120trait FS2Channel [F [_]] extends Channel [F ] {
21+
22+ def input : Pipe [F , Payload , Unit ]
23+ def output : Stream [F , Payload ]
24+
2225 def withEndpoint (endpoint : Endpoint [F ])(implicit F : Functor [F ]): Resource [F , FS2Channel [F ]] =
2326 Resource .make(mountEndpoint(endpoint))(_ => unmountEndpoint(endpoint.method)).map(_ => this )
2427
2528 def withEndpointStream (endpoint : Endpoint [F ])(implicit F : MonadCancelThrow [F ]): Stream [F , FS2Channel [F ]] =
2629 Stream .resource(withEndpoint(endpoint))
2730
2831 def withEndpoints (endpoint : Endpoint [F ], rest : Endpoint [F ]* )(implicit F : Monad [F ]): Resource [F , FS2Channel [F ]] =
29- (endpoint :: rest.toList).traverse_(withEndpoint).as(this )
32+ withEndpoints(endpoint +: rest)
33+
34+ def withEndpoints (endpoints : Seq [Endpoint [F ]])(implicit F : Monad [F ]): Resource [F , FS2Channel [F ]] =
35+ endpoints.toList.traverse_(withEndpoint).as(this )
3036
3137 def withEndpointStream (endpoint : Endpoint [F ], rest : Endpoint [F ]* )(implicit
3238 F : MonadCancelThrow [F ]
3339 ): Stream [F , FS2Channel [F ]] =
3440 Stream .resource(withEndpoints(endpoint, rest : _* ))
3541
36- def open : Resource [ F , Unit ]
37- def openStream : Stream [ F , Unit ]
38- def openStreamForever : Stream [ F , Nothing ]
42+ def withEndpointsStream ( endpoints : Seq [ Endpoint [ F ]])( implicit F : MonadCancelThrow [ F ]) : Stream [ F , FS2Channel [ F ]] =
43+ Stream .resource(withEndpoints(endpoints))
44+
3945}
4046
4147object FS2Channel {
4248
43- def lspCompliant [F [_]: Concurrent ](
44- byteStream : Stream [F , Byte ],
45- byteSink : Pipe [F , Byte , Unit ],
46- bufferSize : Int = 512 ,
47- cancelTemplate : Option [CancelTemplate ] = None
48- ): Stream [F , FS2Channel [F ]] = internals.LSP .writeSink(byteSink, bufferSize).flatMap { sink =>
49- apply[F ](internals.LSP .readStream(byteStream), sink, cancelTemplate)
50- }
51-
5249 def apply [F [_]: Concurrent ](
53- payloadStream : Stream [F , Payload ],
54- payloadSink : Payload => F [Unit ],
50+ bufferSize : Int = 2048 ,
5551 cancelTemplate : Option [CancelTemplate ] = None
5652 ): Stream [F , FS2Channel [F ]] = {
5753 for {
5854 supervisor <- Stream .resource(Supervisor [F ])
5955 ref <- Ref [F ].of(State [F ](Map .empty, Map .empty, Map .empty, 0 )).toStream
60- isOpen <- SignallingRef [F ].of(false ).toStream
61- awaitingSink = isOpen.waitUntil(identity) >> payloadSink(_ : Payload )
62- impl = new Impl (awaitingSink, ref, isOpen, supervisor, cancelTemplate)
56+ queue <- cats.effect.std.Queue .bounded[F , Payload ](bufferSize).toStream
57+ impl = new Impl (queue, ref, supervisor, cancelTemplate)
6358
6459 // Creating a bespoke endpoint to receive cancelation requests
6560 maybeCancelEndpoint : Option [Endpoint [F ]] = cancelTemplate.map { ct =>
@@ -71,10 +66,6 @@ object FS2Channel {
7166 }
7267 // mounting the cancelation endpoint
7368 _ <- maybeCancelEndpoint.traverse_(ep => impl.mountEndpoint(ep)).toStream
74- _ <- Stream (()).concurrently {
75- // Gatekeeping the pull until the channel is actually marked as open
76- payloadStream.pauseWhen(isOpen.map(b => ! b)).evalMap(impl.handleReceivedPayload)
77- }
7869 } yield impl
7970 }
8071
@@ -107,15 +98,17 @@ object FS2Channel {
10798 }
10899
109100 private class Impl [F [_]](
110- private val sink : Payload => F [ Unit ],
101+ private val queue : cats.effect.std. Queue [ F , Payload ],
111102 private val state : Ref [F , FS2Channel .State [F ]],
112- private val isOpen : SignallingRef [F , Boolean ],
113103 supervisor : Supervisor [F ],
114104 maybeCancelTemplate : Option [CancelTemplate ]
115105 )(implicit F : Concurrent [F ])
116106 extends MessageDispatcher [F ]
117107 with FS2Channel [F ] {
118108
109+ def output : Stream [F , Payload ] = Stream .fromQueueUnterminated(queue)
110+ def input : Pipe [F , Payload , Unit ] = _.evalMap(handleReceivedPayload)
111+
119112 def mountEndpoint (endpoint : Endpoint [F ]): F [Unit ] = state
120113 .modify(s =>
121114 s.mountEndpoint(endpoint) match {
@@ -127,10 +120,6 @@ object FS2Channel {
127120
128121 def unmountEndpoint (method : String ): F [Unit ] = state.update(_.removeEndpoint(method))
129122
130- def open : Resource [F , Unit ] = Resource .make[F , Unit ](isOpen.set(true ))(_ => isOpen.set(false ))
131- def openStream : Stream [F , Unit ] = Stream .resource(open)
132- def openStreamForever : Stream [F , Nothing ] = openStream.evalMap(_ => F .never)
133-
134123 protected [fs2] def cancel (callId : CallId ): F [Unit ] = state.get.map(_.runningCalls.get(callId)).flatMap {
135124 case None => F .unit
136125 case Some (fiber) => fiber.cancel
@@ -147,7 +136,7 @@ object FS2Channel {
147136 }
148137 protected def reportError (params : Option [Payload ], error : ProtocolError , method : String ): F [Unit ] = ???
149138 protected def getEndpoint (method : String ): F [Option [Endpoint [F ]]] = state.get.map(_.endpoints.get(method))
150- protected def sendMessage (message : Message ): F [Unit ] = sink (Codec .encode(message))
139+ protected def sendMessage (message : Message ): F [Unit ] = queue.offer (Codec .encode(message))
151140
152141 protected def nextCallId (): F [CallId ] = state.modify(_.nextCallId)
153142 protected def createPromise [A ](callId : CallId ): F [(Try [A ] => F [Unit ], () => F [A ])] = Deferred [F , Try [A ]].map {
0 commit comments