title: key.Exists return true for expired key
body: <p>May be I missed something general, and I am sorry for that.
  But in my tests, when I check expired key (hash) for exists, it returns true:</p>
  
  <p>here "cache" is IDatabase instance</p>
  
  <pre><code>// This will return true
  var exists = cache.KeyExists(key);
  // This will return null
  var ttl = cache.KeyTimeToLive(key);
  // This will return null
  var fullWait = cache.HashGetAsync(key, "full", flags: CommandFlags.None);
  </code></pre>
  
  <p>Also, set with When.NotExists will work:</p>
  
  <pre><code>cache.HashSetAsync(key, "full", value, When.NotExists, CommandFlags.PreferMaster);
  </code></pre>
  
  <p><strong>Update:</strong></p>
  
  <p>@Marc_Gravell answer helped me to find the issue in my tests:
  I am receiving this strange behavior when I am setting up the expiration to be too short (~500 milliseconds).
  When I did change it to be 1 or 2 seconds - my tests are passing now.</p>
  
  <p>In <strong>changed</strong> Marc's example, this also happens ( I changed expiration to 400 ms):</p>
  
  <pre><code>[Test]
      public void Exec()
      {
          var key = "testKey";
          using (var conn = CreateConnection())
          {
              var cache = conn.GetDatabase();
  
              // setup some data
              cache.KeyDelete(key);
  </code></pre>
  
  <p>//                cache.HashSet(key, "full", "some value");
  //                cache.KeyExpire(key, TimeSpan.FromSeconds(3));</p>
  
  <pre><code>            cache.HashSetAsync(key, "full", "some value", When.NotExists, CommandFlags.PreferMaster);
              cache.HashSetAsync(key, "last_accessesed", "some other data", When.NotExists, CommandFlags.PreferMaster);
              cache.KeyExpireAsync(key, DateTime.UtcNow.AddMilliseconds(400), CommandFlags.FireAndForget);
  
  
  
              // test while exists
              var exists = cache.KeyExists(key);
              var ttl = cache.KeyTimeToLive(key);
              var fullWait = cache.HashGetAsync(key, "full", flags: CommandFlags.None);
              Assert.IsTrue(exists, "key exists");
              Assert.IsNotNull(ttl, "ttl");
              Assert.AreEqual("some value", (string)fullWait.Result);
  </code></pre>
  
  <p>brings</p>
  
  <pre><code>  ttl
    Expected: not null
    But was:  null
  </code></pre>
  
  <p><strong>Update 2:</strong></p>
  
  <p>This code worked fine for me yesterday, but does not work now.</p>
  
  <pre><code>   private ConnectionMultiplexer CreateConnection()
      {
          ConnectionMultiplexer connection =ConnectionMultiplexer.Connect(
       "myserver.redis.cache.windows.net,ssl=false,password=password-here");
  
          return connection;
      }
  
          [Ignore]
          [Test]
          public void Exec()
          {
          var key = "testKey";
          using (var conn = CreateConnection())
          {
              var cache = conn.GetDatabase();
  
              // setup some data
              cache.KeyDelete(key);
              cache.HashSetAsync(key, "full", "some value", When.NotExists, CommandFlags.PreferMaster);
              cache.HashSetAsync(key, "last_accessesed", "some other data", When.NotExists, CommandFlags.PreferMaster);
              cache.KeyExpireAsync(key, DateTime.UtcNow.AddMilliseconds(2000), CommandFlags.FireAndForget);
  
              // test while exists
              var exists = cache.KeyExists(key);
              var ttl = cache.KeyTimeToLive(key);
              var fullWait = cache.HashGetAsync(key, "full", flags: CommandFlags.None);
              Assert.IsTrue(exists, "not expired key exists");
              Assert.IsNotNull(ttl, "ttl");
              Assert.AreEqual("some value", (string)fullWait.Result);
  
              // wait for expiry
              Thread.Sleep(TimeSpan.FromMilliseconds(5000));
  
              // test once expired
              exists = cache.KeyExists(key);
              ttl = cache.KeyTimeToLive(key);
              fullWait = cache.HashGetAsync(key, "full", flags: CommandFlags.None);
              Assert.IsFalse(exists, "expired key exists");
              Assert.IsNull(ttl, "ttl");
              Assert.IsNull((string)fullWait.Result);
          }
      }
  </code></pre>
  
  <p>Line </p>
  
  <pre><code>Assert.IsFalse(exists, "expired key exists");
  </code></pre>
  
  <p>returns   </p>
  
  <pre><code>  expired key exists
    Expected: False
    But was:  True
  </code></pre>
  
  <p>Changing to use seconds did not help:</p>
  
  <pre><code>  cache.KeyExpireAsync(key, DateTime.UtcNow.AddSeconds(3), CommandFlags.FireAndForget);
    ...
    // wait for expiry
    Thread.Sleep(TimeSpan.FromSeconds(10));
  </code></pre>
  
  <p>returns same result ( Assert.IsFalse(exists, "expired key exists"))</p>
  
  <pre><code>  expired key exists
    Expected: False
    But was:  True
  </code></pre>