Giter Club home page Giter Club logo

Comments (4)

ericchapman avatar ericchapman commented on May 28, 2024

I got a chance to look at this. I was able to resolve this at the RedisClient level. I did the following

  • In RedisClient -> Send
    • Store the promise when it is created
      • Note I used a dictionary since the array "removeObject" is now a pain in Swift
    • Remove the promise when it is fulfilled (future.always)
  • In RedisClient -> Init -> channel.closureFuture.always
    • Iterate through the stored promises and send a "ChannelError"
    • Empty the storage object

Diff below

bash-3.2$ git diff
diff --git a/Sources/Redis/Client/RedisClient.swift b/Sources/Redis/Client/RedisClient.swift
index 177277a..901ec86 100644
--- a/Sources/Redis/Client/RedisClient.swift
+++ b/Sources/Redis/Client/RedisClient.swift
@@ -20,7 +20,10 @@ public final class RedisClient: DatabaseConnection, BasicWorker {
 
     /// The channel
     private let channel: Channel
-
+    
+    /// Stores the inflight promises so they can be fulfilled when the channel drops
+    var inflightPromises: [String:EventLoopPromise<RedisData>] = [:]
+    
     /// Creates a new Redis client on the provided data source and sink.
     init(queue: RedisCommandHandler, channel: Channel) {
         self.queue = queue
@@ -28,6 +31,12 @@ public final class RedisClient: DatabaseConnection, BasicWorker {
         self.extend = [:]
         self.isClosed = false
         channel.closeFuture.always {
+            // send closed error for the promises that have not been fulfilled
+            for promise in self.inflightPromises.values {
+                promise.fail(error: ChannelError.ioOnClosedChannel)
+            }
+            self.inflightPromises.removeAll()
+            
             self.isClosed = true
         }
     }
@@ -55,6 +64,13 @@ public final class RedisClient: DatabaseConnection, BasicWorker {
         // create a new promise to fulfill later
         let promise = eventLoop.newPromise(RedisData.self)
         
+        // logic to store in-flight requests
+        let key = UUID().uuidString
+        self.inflightPromises[key] = promise
+        promise.futureResult.always {
+            self.inflightPromises.removeValue(forKey: key)
+        }
+        
         // write the message and the promise to the channel, which the `RequestResponseHandler` will capture
         return self.channel.writeAndFlush((message, promise))
             .flatMap { return promise.futureResult }

@Mordil If this solution is acceptable, I'll create a PR accordingly. Let me know what you think

from redis.

ericchapman avatar ericchapman commented on May 28, 2024

@Mordil I created a PR for this. Use it if you desire. I needed to fix it for my needs regardless.

from redis.

Mordil avatar Mordil commented on May 28, 2024

@ericchapman Sorry for the extremely long delay in response - August has been way too busy for me.

I left a comment on the PR of where the code can live. The primary thing is the handler is missing a good implementation for either channelInactive or something else to respond to the channel now closing - which is honestly a problem upstream w/ SwiftNIO Extras as well

from redis.

ericchapman avatar ericchapman commented on May 28, 2024

@Mordil That was what I was looking for! I knew the in-flight promises were stored somewhere already. I just needed to go a level deeper in the code. Let me know if my modified code is correct. And no problem being busy. It happens to all of us.

from redis.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.