@@ -30,6 +30,8 @@ type Plugin struct {
3030 ScanCount int64
3131 ExitOnStartupError bool
3232
33+ UpdateCacheChannel chan * v1.Struct
34+
3335 // Periodic invalidator configuration.
3436 PeriodicInvalidatorEnabled bool
3537 PeriodicInvalidatorStartDelay time.Duration
@@ -144,87 +146,103 @@ func (p *Plugin) OnTrafficFromClient(
144146 return req , nil
145147}
146148
147- // OnTrafficFromServer is called when a response is received by GatewayD from the server.
148- func (p * Plugin ) OnTrafficFromServer (
149- ctx context.Context , resp * v1.Struct ,
150- ) (* v1.Struct , error ) {
151- OnTrafficFromServerCounter .Inc ()
152- resp , err := postgres .HandleServerMessage (resp , p .Logger )
153- if err != nil {
154- p .Logger .Info ("Failed to handle server message" , "error" , err )
155- }
156-
157- rowDescription := cast .ToString (sdkPlugin .GetAttr (resp , "rowDescription" , "" ))
158- dataRow := cast .ToStringSlice (sdkPlugin .GetAttr (resp , "dataRow" , []interface {}{}))
159- errorResponse := cast .ToString (sdkPlugin .GetAttr (resp , "errorResponse" , "" ))
160- request , ok := sdkPlugin .GetAttr (resp , "request" , nil ).([]byte )
161- if ! ok {
162- request = []byte {}
163- }
164- response , ok := sdkPlugin .GetAttr (resp , "response" , nil ).([]byte )
165- if ! ok {
166- response = []byte {}
167- }
168- server := cast .ToStringMapString (sdkPlugin .GetAttr (resp , "server" , "" ))
149+ func (p * Plugin ) UpdateCache (ctx context.Context ) {
150+ for {
151+ serverResponse , ok := <- p .UpdateCacheChannel
152+ if ! ok {
153+ p .Logger .Info ("Channel closed, returning from function" )
154+ return
155+ }
169156
170- // This is used as a fallback if the database is not found in the startup message.
171- database := p .DefaultDBName
172- if database == "" {
173- client := cast .ToStringMapString (sdkPlugin .GetAttr (resp , "client" , "" ))
174- if client != nil && client ["remote" ] != "" {
175- database , err = p .RedisClient .Get (ctx , client ["remote" ]).Result ()
176- if err != nil {
177- CacheMissesCounter .Inc ()
178- p .Logger .Debug ("Failed to get cached response" , "error" , err )
179- }
180- CacheGetsCounter .Inc ()
157+ OnTrafficFromServerCounter .Inc ()
158+ resp , err := postgres .HandleServerMessage (serverResponse , p .Logger )
159+ if err != nil {
160+ p .Logger .Info ("Failed to handle server message" , "error" , err )
181161 }
182- }
183162
184- // If the database is still not found, return the response as is without caching.
185- // This might also happen if the cache is cleared while the client is still connected.
186- // In this case, the client should reconnect and the error will go away.
187- if database == "" {
188- p .Logger .Debug ("Database name not found or set in cache, startup message or plugin config. Skipping cache" )
189- p .Logger .Debug ("Consider setting the database name in the plugin config or disabling the plugin if you don't need it" )
190- return resp , nil
191- }
163+ rowDescription := cast .ToString (sdkPlugin .GetAttr (resp , "rowDescription" , "" ))
164+ dataRow := cast .ToStringSlice (sdkPlugin .GetAttr (resp , "dataRow" , []interface {}{}))
165+ errorResponse := cast .ToString (sdkPlugin .GetAttr (resp , "errorResponse" , "" ))
166+ request , isOk := sdkPlugin .GetAttr (resp , "request" , nil ).([]byte )
167+ if ! isOk {
168+ request = []byte {}
169+ }
192170
193- cacheKey := strings .Join ([]string {server ["remote" ], database , string (request )}, ":" )
194- if errorResponse == "" && rowDescription != "" && dataRow != nil && len (dataRow ) > 0 {
195- // The request was successful and the response contains data. Cache the response.
196- if err := p .RedisClient .Set (ctx , cacheKey , response , p .Expiry ).Err (); err != nil {
197- CacheMissesCounter .Inc ()
198- p .Logger .Debug ("Failed to set cache" , "error" , err )
171+ response , isOk := sdkPlugin .GetAttr (resp , "response" , nil ).([]byte )
172+ if ! isOk {
173+ response = []byte {}
199174 }
200- CacheSetsCounter . Inc ( )
175+ server := cast . ToStringMapString ( sdkPlugin . GetAttr ( resp , "server" , "" ) )
201176
202- // Cache the query as well.
203- query , err := postgres .GetQueryFromRequest (request )
204- if err != nil {
205- p .Logger .Debug ("Failed to get query from request" , "error" , err )
206- return resp , nil
177+ // This is used as a fallback if the database is not found in the startup message.
178+
179+ database := p .DefaultDBName
180+ if database == "" {
181+ client := cast .ToStringMapString (sdkPlugin .GetAttr (resp , "client" , "" ))
182+ if client != nil && client ["remote" ] != "" {
183+ database , err = p .RedisClient .Get (ctx , client ["remote" ]).Result ()
184+ if err != nil {
185+ CacheMissesCounter .Inc ()
186+ p .Logger .Debug ("Failed to get cached response" , "error" , err )
187+ }
188+ CacheGetsCounter .Inc ()
189+ }
207190 }
208191
209- tables , err := postgres .GetTablesFromQuery (query )
210- if err != nil {
211- p .Logger .Debug ("Failed to get tables from query" , "error" , err )
212- return resp , nil
192+ // If the database is still not found, return the response as is without caching.
193+ // This might also happen if the cache is cleared while the client is still connected.
194+ // In this case, the client should reconnect and the error will go away.
195+ if database == "" {
196+ p .Logger .Debug ("Database name not found or set in cache, startup message or plugin config. " +
197+ "Skipping cache" )
198+ p .Logger .Debug ("Consider setting the database name in the " +
199+ "plugin config or disabling the plugin if you don't need it" )
200+ return
213201 }
214202
215- // Cache the table(s) used in each cached request. This is used to invalidate
216- // the cache when a rows is inserted, updated or deleted into that table.
217- for _ , table := range tables {
218- requestQueryCacheKey := strings .Join ([]string {table , cacheKey }, ":" )
219- if err := p .RedisClient .Set (
220- ctx , requestQueryCacheKey , "" , p .Expiry ).Err (); err != nil {
203+ cacheKey := strings .Join ([]string {server ["remote" ], database , string (request )}, ":" )
204+ if errorResponse == "" && rowDescription != "" && dataRow != nil && len (dataRow ) > 0 {
205+ // The request was successful and the response contains data. Cache the response.
206+ if err := p .RedisClient .Set (ctx , cacheKey , response , p .Expiry ).Err (); err != nil {
221207 CacheMissesCounter .Inc ()
222208 p .Logger .Debug ("Failed to set cache" , "error" , err )
223209 }
224210 CacheSetsCounter .Inc ()
211+
212+ // Cache the query as well.
213+ query , err := postgres .GetQueryFromRequest (request )
214+ if err != nil {
215+ p .Logger .Debug ("Failed to get query from request" , "error" , err )
216+ return
217+ }
218+
219+ tables , err := postgres .GetTablesFromQuery (query )
220+ if err != nil {
221+ p .Logger .Debug ("Failed to get tables from query" , "error" , err )
222+ return
223+ }
224+
225+ // Cache the table(s) used in each cached request. This is used to invalidate
226+ // the cache when a rows is inserted, updated or deleted into that table.
227+ for _ , table := range tables {
228+ requestQueryCacheKey := strings .Join ([]string {table , cacheKey }, ":" )
229+ if err := p .RedisClient .Set (
230+ ctx , requestQueryCacheKey , "" , p .Expiry ).Err (); err != nil {
231+ CacheMissesCounter .Inc ()
232+ p .Logger .Debug ("Failed to set cache" , "error" , err )
233+ }
234+ CacheSetsCounter .Inc ()
235+ }
225236 }
226237 }
238+ }
227239
240+ // OnTrafficFromServer is called when a response is received by GatewayD from the server.
241+ func (p * Plugin ) OnTrafficFromServer (
242+ _ context.Context , resp * v1.Struct ,
243+ ) (* v1.Struct , error ) {
244+ p .Logger .Debug ("Traffic is coming from the server side" )
245+ p .UpdateCacheChannel <- resp
228246 return resp , nil
229247}
230248
0 commit comments