danieleteti / delphimvcframework

DMVCFramework (for short) is a popular and powerful framework for WEB API in Delphi. Supports RESTful and JSON-RPC WEB APIs development.
Apache License 2.0
1.23k stars 356 forks source link

Fixed issue with DeleteCacheKey method #733

Closed gmurt closed 7 months ago

gmurt commented 7 months ago

Fixed issue where an exception is raised if KEYS() finds no matches and returns null

danieleteti commented 7 months ago

Key is not the right command today... can you do some test to availd the key scanning? In the following page there are some suggestions.

https://stackoverflow.com/questions/8744207/finding-keys-using-wildcards

gmurt commented 7 months ago

Sure, I'll have a play with this later this evening. Wasn't sure if a pull request was the correct thing to do or add it to the issues. (Obviously an issue with my code from the last pull request, not your code)

gmurt commented 7 months ago

This is the scan method I have written for the Redis.Client. It appears to work but I'm sure I've not implemented this in the correct way as I needed to add JsonDataObjects to the uses clause to prevent some "... has not been expanded" warnings.

I'm not very familiar with Git so don't know if I should be add this to "issues", posting my code here or creating a new pull request. Perhaps you could advise on what you recommend.

procedure TRedisClient.SCAN(aPattern: string; aCallback: TProc<TArray<string>>);
var
  lCmd: IRedisCommand;
  aCursor: integer;
  AResp: TRedisRESPArray;
  AKey: string;
  Values: TArray<string>;
begin
  aCursor := 0;
  repeat
    lCmd := NewRedisCommand('SCAN');
    lCmd.Add(aCursor);
    lCmd.Add('MATCH');
    lCmd.Add(Apattern);
    AResp := ExecuteAndGetRESPArray(lCmd);
    ACursor := AResp.I[0];
    SetLength(Values, 0);
    for AKey in AResp[1].ArrayValue do
      Values := Values + [AKey];
    aCallback(Values);
  until aCursor = 0;
end;

Which is called in my code with...

  FRedis.SCAN(APattern,
    procedure(AKeys: TArray<string>)
    begin
      FRedis.DEL(AKeys);
    end
  );
danieleteti commented 7 months ago

I did the changes to delphiredisclient as well (with a small fix related to a memory leak).

The new code added supports SCAN command and is testes as following:

procedure TestRedisClient.TestSCAN;
begin
  FRedis.&SET('A1','v1');
  FRedis.&SET('A2','v1');
  FRedis.&SET('A3','v1');
  CheckTrue(FRedis.EXISTS('A1'));
  CheckTrue(FRedis.EXISTS('A2'));
  CheckTrue(FRedis.EXISTS('A3'));
  FRedis.SCAN('A*',
    procedure(Topics: TArray<string>)
    begin
      if Length(Topics) > 0 then
      begin
        FRedis.DEL(topics);
      end;
    end);
  CheckFalse(FRedis.EXISTS('A1'));
  CheckFalse(FRedis.EXISTS('A2'));
  CheckFalse(FRedis.EXISTS('A3'));
end;