jellydator / ttlcache Goto Github PK
View Code? Open in Web Editor NEWAn in-memory cache with item expiration and generics
License: MIT License
An in-memory cache with item expiration and generics
License: MIT License
Is it possible to call expirationCallback on each remaining keys in the cache, when calling cache.Close()?
The purpose is to keep the overall expirationCallback behavior the same?
// Setup the TTL cache
cache := ttlcache.NewCache()
cache.SetTTL(time.Second * 10)
cache.SetExpirationCallback(func(key string, value interface{}) {
fmt.Printf("This key(%s) has expired\n", key)
})
for i := 0; ; i++ {
cache.Set(fmt.Sprintf("item_%d", i), clientPlatformService{})
time.Sleep(time.Millisecond * 100)
log.Println("Cache size:", cache.Count())
}
2017/07/31 10:30:57 Cache size: 1
2017/07/31 10:30:57 Cache size: 2
2017/07/31 10:30:57 Cache size: 3
2017/07/31 10:30:57 Cache size: 4
2017/07/31 10:30:58 Cache size: 5
2017/07/31 10:30:58 Cache size: 6
2017/07/31 10:30:58 Cache size: 7
2017/07/31 10:30:58 Cache size: 8
2017/07/31 10:30:58 Cache size: 9
2017/07/31 10:30:58 Cache size: 10
2017/07/31 10:30:58 Cache size: 11
2017/07/31 10:30:58 Cache size: 12
2017/07/31 10:30:58 Cache size: 13
2017/07/31 10:30:58 Cache size: 14
2017/07/31 10:30:59 Cache size: 15
2017/07/31 10:30:59 Cache size: 16
2017/07/31 10:30:59 Cache size: 17
2017/07/31 10:30:59 Cache size: 18
2017/07/31 10:30:59 Cache size: 19
2017/07/31 10:30:59 Cache size: 20
2017/07/31 10:30:59 Cache size: 21
2017/07/31 10:30:59 Cache size: 22
2017/07/31 10:30:59 Cache size: 23
2017/07/31 10:31:00 Cache size: 24
2017/07/31 10:31:00 Cache size: 25
2017/07/31 10:31:00 Cache size: 26
2017/07/31 10:31:00 Cache size: 27
2017/07/31 10:31:00 Cache size: 28
2017/07/31 10:31:00 Cache size: 29
2017/07/31 10:31:00 Cache size: 30
2017/07/31 10:31:00 Cache size: 31
2017/07/31 10:31:00 Cache size: 32
2017/07/31 10:31:00 Cache size: 33
2017/07/31 10:31:01 Cache size: 34
2017/07/31 10:31:01 Cache size: 35
2017/07/31 10:31:01 Cache size: 36
2017/07/31 10:31:01 Cache size: 37
2017/07/31 10:31:01 Cache size: 38
2017/07/31 10:31:01 Cache size: 39
2017/07/31 10:31:01 Cache size: 40
2017/07/31 10:31:01 Cache size: 41
2017/07/31 10:31:01 Cache size: 42
2017/07/31 10:31:01 Cache size: 43
2017/07/31 10:31:02 Cache size: 44
2017/07/31 10:31:02 Cache size: 45
2017/07/31 10:31:02 Cache size: 46
2017/07/31 10:31:02 Cache size: 47
2017/07/31 10:31:02 Cache size: 48
2017/07/31 10:31:02 Cache size: 49
2017/07/31 10:31:02 Cache size: 50
2017/07/31 10:31:02 Cache size: 51
2017/07/31 10:31:02 Cache size: 52
2017/07/31 10:31:02 Cache size: 53
2017/07/31 10:31:03 Cache size: 54
2017/07/31 10:31:03 Cache size: 55
2017/07/31 10:31:03 Cache size: 56
2017/07/31 10:31:03 Cache size: 57
2017/07/31 10:31:03 Cache size: 58
2017/07/31 10:31:03 Cache size: 59
2017/07/31 10:31:03 Cache size: 60
2017/07/31 10:31:03 Cache size: 61
2017/07/31 10:31:03 Cache size: 62
2017/07/31 10:31:04 Cache size: 63
2017/07/31 10:31:04 Cache size: 64
2017/07/31 10:31:04 Cache size: 65
2017/07/31 10:31:04 Cache size: 66
2017/07/31 10:31:04 Cache size: 67
2017/07/31 10:31:04 Cache size: 68
2017/07/31 10:31:04 Cache size: 69
2017/07/31 10:31:04 Cache size: 70
2017/07/31 10:31:04 Cache size: 71
2017/07/31 10:31:04 Cache size: 72
2017/07/31 10:31:05 Cache size: 73
2017/07/31 10:31:05 Cache size: 74
2017/07/31 10:31:05 Cache size: 75
2017/07/31 10:31:05 Cache size: 76
2017/07/31 10:31:05 Cache size: 77
2017/07/31 10:31:05 Cache size: 78
2017/07/31 10:31:05 Cache size: 79
2017/07/31 10:31:05 Cache size: 80
2017/07/31 10:31:05 Cache size: 81
2017/07/31 10:31:05 Cache size: 82
2017/07/31 10:31:06 Cache size: 83
2017/07/31 10:31:06 Cache size: 84
2017/07/31 10:31:06 Cache size: 85
2017/07/31 10:31:06 Cache size: 86
2017/07/31 10:31:06 Cache size: 87
2017/07/31 10:31:06 Cache size: 88
2017/07/31 10:31:06 Cache size: 89
2017/07/31 10:31:06 Cache size: 90
2017/07/31 10:31:06 Cache size: 91
2017/07/31 10:31:07 Cache size: 92
2017/07/31 10:31:07 Cache size: 93
2017/07/31 10:31:07 Cache size: 94
2017/07/31 10:31:07 Cache size: 95
2017/07/31 10:31:07 Cache size: 96
2017/07/31 10:31:07 Cache size: 97
This key(item_0) has expired
2017/07/31 10:31:07 Cache size: 97
This key(item_1) has expired
2017/07/31 10:31:07 Cache size: 97
This key(item_2) has expired
2017/07/31 10:31:07 Cache size: 97
This key(item_3) has expired
2017/07/31 10:31:07 Cache size: 97
This key(item_4) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_5) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_6) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_7) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_8) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_9) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_10) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_11) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_12) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_13) has expired
2017/07/31 10:31:08 Cache size: 97
This key(item_14) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_15) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_16) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_17) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_18) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_19) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_20) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_21) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_22) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_23) has expired
2017/07/31 10:31:09 Cache size: 97
This key(item_24) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_25) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_26) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_27) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_28) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_29) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_30) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_31) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_32) has expired
2017/07/31 10:31:10 Cache size: 97
This key(item_33) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_34) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_35) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_36) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_37) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_38) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_39) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_40) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_41) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_42) has expired
2017/07/31 10:31:11 Cache size: 97
This key(item_43) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_44) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_45) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_46) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_47) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_48) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_49) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_50) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_51) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_52) has expired
2017/07/31 10:31:12 Cache size: 97
This key(item_53) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_54) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_55) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_56) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_57) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_58) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_59) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_60) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_61) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_62) has expired
2017/07/31 10:31:13 Cache size: 97
This key(item_63) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_64) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_65) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_66) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_67) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_68) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_69) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_70) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_71) has expired
2017/07/31 10:31:14 Cache size: 97
This key(item_72) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_73) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_74) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_75) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_76) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_77) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_78) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_79) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_80) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_81) has expired
2017/07/31 10:31:15 Cache size: 97
This key(item_82) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_83) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_84) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_85) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_86) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_87) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_88) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_89) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_90) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_91) has expired
2017/07/31 10:31:16 Cache size: 97
This key(item_92) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_93) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_94) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_95) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_96) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_97) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_98) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_99) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_100) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_101) has expired
2017/07/31 10:31:17 Cache size: 97
This key(item_102) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_103) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_104) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_105) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_106) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_107) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_108) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_109) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_110) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_111) has expired
2017/07/31 10:31:18 Cache size: 97
This key(item_112) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_113) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_114) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_115) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_116) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_117) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_118) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_119) has expired
2017/07/31 10:31:19 Cache size: 97
This key(item_120) has expired
2017/07/31 10:31:19 Cache size: 97
2017/07/31 10:31:19 Cache size: 98
This key(item_121) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_122) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_123) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_124) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_125) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_126) has expired
2017/07/31 10:31:20 Cache size: 98
This key(item_127) has expired
This key(item_128) has expired
2017/07/31 10:31:20 Cache size: 97
This key(item_129) has expired
2017/07/31 10:31:20 Cache size: 97
2017/07/31 10:31:20 Cache size: 97
This key(item_130) has expired
2017/07/31 10:31:21 Cache size: 97
This key(item_131) has expired
2017/07/31 10:31:21 Cache size: 98
This key(item_132) has expired
2017/07/31 10:31:21 Cache size: 98
This key(item_133) has expired
This key(item_134) has expired
2017/07/31 10:31:21 Cache size: 97
2017/07/31 10:31:21 Cache size: 98
This key(item_135) has expired
This key(item_136) has expired
2017/07/31 10:31:21 Cache size: 97
2017/07/31 10:31:21 Cache size: 97
This key(item_137) has expired
2017/07/31 10:31:21 Cache size: 98
This key(item_138) has expired
2017/07/31 10:31:21 Cache size: 98
This key(item_139) has expired
2017/07/31 10:31:21 Cache size: 98
This key(item_140) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_141) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_142) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_143) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_144) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_145) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_146) has expired
2017/07/31 10:31:22 Cache size: 98
This key(item_147) has expired
2017/07/31 10:31:22 Cache size: 97
This key(item_148) has expired
2017/07/31 10:31:22 Cache size: 97
This key(item_149) has expired
This key(item_150) has expired
2017/07/31 10:31:22 Cache size: 97
2017/07/31 10:31:23 Cache size: 98
This key(item_151) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_152) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_153) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_154) has expired
2017/07/31 10:31:23 Cache size: 97
This key(item_155) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_156) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_157) has expired
This key(item_158) has expired
2017/07/31 10:31:23 Cache size: 97
2017/07/31 10:31:23 Cache size: 98
This key(item_159) has expired
2017/07/31 10:31:23 Cache size: 98
This key(item_160) has expired
2017/07/31 10:31:24 Cache size: 98
This key(item_161) has expired
2017/07/31 10:31:24 Cache size: 97
This key(item_162) has expired
This key(item_163) has expired
2017/07/31 10:31:24 Cache size: 97
2017/07/31 10:31:24 Cache size: 97
This key(item_164) has expired
2017/07/31 10:31:24 Cache size: 98
This key(item_165) has expired
This key(item_166) has expired
2017/07/31 10:31:24 Cache size: 97
This key(item_167) has expired
2017/07/31 10:31:24 Cache size: 97
This key(item_168) has expired
2017/07/31 10:31:24 Cache size: 97
This key(item_169) has expired
2017/07/31 10:31:24 Cache size: 97
2017/07/31 10:31:25 Cache size: 98
This key(item_170) has expired
This key(item_171) has expired
2017/07/31 10:31:25 Cache size: 97
This key(item_172) has expired
2017/07/31 10:31:25 Cache size: 97
This key(item_173) has expired
2017/07/31 10:31:25 Cache size: 97
This key(item_174) has expired
2017/07/31 10:31:25 Cache size: 97
2017/07/31 10:31:25 Cache size: 98
This key(item_175) has expired
2017/07/31 10:31:25 Cache size: 98
This key(item_176) has expired
2017/07/31 10:31:25 Cache size: 98
This key(item_177) has expired
2017/07/31 10:31:25 Cache size: 98
This key(item_178) has expired
2017/07/31 10:31:25 Cache size: 98
This key(item_179) has expired
2017/07/31 10:31:26 Cache size: 97
This key(item_180) has expired
This key(item_181) has expired
2017/07/31 10:31:26 Cache size: 97
2017/07/31 10:31:26 Cache size: 98
This key(item_182) has expired
2017/07/31 10:31:26 Cache size: 98
This key(item_183) has expired
2017/07/31 10:31:26 Cache size: 97
This key(item_184) has expired
This key(item_185) has expired
2017/07/31 10:31:26 Cache size: 97
2017/07/31 10:31:26 Cache size: 98
This key(item_186) has expired
2017/07/31 10:31:26 Cache size: 98
This key(item_187) has expired
2017/07/31 10:31:26 Cache size: 98
This key(item_188) has expired
This key(item_189) has expired
2017/07/31 10:31:26 Cache size: 97
This key(item_190) has expired
2017/07/31 10:31:27 Cache size: 97
2017/07/31 10:31:27 Cache size: 98
This key(item_191) has expired
2017/07/31 10:31:27 Cache size: 97
This key(item_192) has expired
2017/07/31 10:31:27 Cache size: 97
This key(item_193) has expired
2017/07/31 10:31:27 Cache size: 98
This key(item_194) has expired
This key(item_195) has expired
2017/07/31 10:31:27 Cache size: 97
This key(item_196) has expired
2017/07/31 10:31:27 Cache size: 97
This key(item_197) has expired
2017/07/31 10:31:27 Cache size: 97
2017/07/31 10:31:27 Cache size: 98
This key(item_198) has expired
This key(item_199) has expired
2017/07/31 10:31:27 Cache size: 97
This key(item_200) has expired
2017/07/31 10:31:28 Cache size: 97
This key(item_201) has expired
2017/07/31 10:31:28 Cache size: 97
2017/07/31 10:31:28 Cache size: 98
This key(item_202) has expired
This key(item_203) has expired
2017/07/31 10:31:28 Cache size: 97
2017/07/31 10:31:28 Cache size: 98
This key(item_204) has expired
2017/07/31 10:31:28 Cache size: 97
This key(item_205) has expired
This key(item_206) has expired
2017/07/31 10:31:28 Cache size: 97
This key(item_207) has expired
2017/07/31 10:31:28 Cache size: 97
2017/07/31 10:31:28 Cache size: 98
This key(item_208) has expired
2017/07/31 10:31:28 Cache size: 98
This key(item_209) has expired
This key(item_210) has expired
2017/07/31 10:31:29 Cache size: 98
This key(item_211) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_212) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_213) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_214) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_215) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_216) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_217) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_218) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_219) has expired
2017/07/31 10:31:29 Cache size: 97
This key(item_220) has expired
2017/07/31 10:31:30 Cache size: 97
This key(item_221) has expired
2017/07/31 10:31:30 Cache size: 97
This key(item_222) has expired
2017/07/31 10:31:30 Cache size: 97
2017/07/31 10:31:30 Cache size: 97
This key(item_223) has expired
2017/07/31 10:31:30 Cache size: 98
This key(item_224) has expired
2017/07/31 10:31:30 Cache size: 98
This key(item_225) has expired
2017/07/31 10:31:30 Cache size: 98
This key(item_226) has expired
This key(item_227) has expired
2017/07/31 10:31:30 Cache size: 97
2017/07/31 10:31:30 Cache size: 98
This key(item_228) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_229) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_230) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_231) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_232) has expired
This key(item_233) has expired
2017/07/31 10:31:31 Cache size: 97
2017/07/31 10:31:31 Cache size: 98
This key(item_234) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_235) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_236) has expired
2017/07/31 10:31:31 Cache size: 98
This key(item_237) has expired
This key(item_238) has expired
2017/07/31 10:31:31 Cache size: 97
This key(item_239) has expired
2017/07/31 10:31:32 Cache size: 97
2017/07/31 10:31:32 Cache size: 98
This key(item_240) has expired
This key(item_241) has expired
2017/07/31 10:31:32 Cache size: 97
2017/07/31 10:31:32 Cache size: 97
This key(item_242) has expired
This key(item_243) has expired
2017/07/31 10:31:32 Cache size: 97
2017/07/31 10:31:32 Cache size: 98
This key(item_244) has expired
2017/07/31 10:31:32 Cache size: 98
This key(item_245) has expired
2017/07/31 10:31:32 Cache size: 98
This key(item_246) has expired
2017/07/31 10:31:32 Cache size: 98
This key(item_247) has expired
2017/07/31 10:31:32 Cache size: 98
This key(item_248) has expired
This key(item_249) has expired
2017/07/31 10:31:33 Cache size: 97
This key(item_250) has expired
2017/07/31 10:31:33 Cache size: 97
2017/07/31 10:31:33 Cache size: 98
This key(item_251) has expired
2017/07/31 10:31:33 Cache size: 98
This key(item_252) has expired
2017/07/31 10:31:33 Cache size: 98
This key(item_253) has expired
2017/07/31 10:31:33 Cache size: 98
This key(item_254) has expired
This key(item_255) has expired
2017/07/31 10:31:33 Cache size: 97
This key(item_256) has expired
2017/07/31 10:31:33 Cache size: 97
This key(item_257) has expired
2017/07/31 10:31:33 Cache size: 97
This key(item_258) has expired
2017/07/31 10:31:33 Cache size: 97
2017/07/31 10:31:34 Cache size: 98
This key(item_259) has expired
This key(item_260) has expired
2017/07/31 10:31:34 Cache size: 97
2017/07/31 10:31:34 Cache size: 97
This key(item_261) has expired
2017/07/31 10:31:34 Cache size: 97
This key(item_262) has expired
This key(item_263) has expired
2017/07/31 10:31:34 Cache size: 97
2017/07/31 10:31:34 Cache size: 98
This key(item_264) has expired
This key(item_265) has expired
2017/07/31 10:31:34 Cache size: 97
This key(item_266) has expired
2017/07/31 10:31:34 Cache size: 97
2017/07/31 10:31:34 Cache size: 97
This key(item_267) has expired
2017/07/31 10:31:35 Cache size: 98
This key(item_268) has expired
2017/07/31 10:31:35 Cache size: 98
This key(item_269) has expired
2017/07/31 10:31:35 Cache size: 97
This key(item_270) has expired
2017/07/31 10:31:35 Cache size: 98
This key(item_271) has expired
This key(item_272) has expired
2017/07/31 10:31:35 Cache size: 97
This key(item_273) has expired
2017/07/31 10:31:35 Cache size: 97
This key(item_274) has expired
2017/07/31 10:31:35 Cache size: 97
This key(item_275) has expired
2017/07/31 10:31:35 Cache size: 97
2017/07/31 10:31:35 Cache size: 97
This key(item_276) has expired
2017/07/31 10:31:35 Cache size: 98
This key(item_277) has expired
2017/07/31 10:31:36 Cache size: 97
This key(item_278) has expired
2017/07/31 10:31:36 Cache size: 98
This key(item_279) has expired
2017/07/31 10:31:36 Cache size: 98
This key(item_280) has expired
This key(item_281) has expired
2017/07/31 10:31:36 Cache size: 97
This key(item_282) has expired
2017/07/31 10:31:36 Cache size: 97
2017/07/31 10:31:36 Cache size: 98
This key(item_283) has expired
2017/07/31 10:31:36 Cache size: 98
This key(item_284) has expired
2017/07/31 10:31:36 Cache size: 98
This key(item_285) has expired
2017/07/31 10:31:36 Cache size: 98
This key(item_286) has expired
This key(item_287) has expired
2017/07/31 10:31:36 Cache size: 97
2017/07/31 10:31:37 Cache size: 98
This key(item_288) has expired
This key(item_289) has expired
2017/07/31 10:31:37 Cache size: 97
2017/07/31 10:31:37 Cache size: 98
This key(item_290) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_291) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_292) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_293) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_294) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_295) has expired
2017/07/31 10:31:37 Cache size: 97
This key(item_296) has expired
2017/07/31 10:31:37 Cache size: 98
This key(item_297) has expired
2017/07/31 10:31:38 Cache size: 97
This key(item_298) has expired
2017/07/31 10:31:38 Cache size: 98
This key(item_299) has expired
2017/07/31 10:31:38 Cache size: 98
This key(item_300) has expired
2017/07/31 10:31:38 Cache size: 97
This key(item_301) has expired
This key(item_302) has expired
2017/07/31 10:31:38 Cache size: 97
2017/07/31 10:31:38 Cache size: 97
This key(item_303) has expired
This key(item_304) has expired
2017/07/31 10:31:38 Cache size: 97
2017/07/31 10:31:38 Cache size: 98
This key(item_305) has expired
2017/07/31 10:31:38 Cache size: 98
This key(item_306) has expired
2017/07/31 10:31:38 Cache size: 98
This key(item_307) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_308) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_309) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_310) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_311) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_312) has expired
2017/07/31 10:31:39 Cache size: 97
This key(item_313) has expired
2017/07/31 10:31:39 Cache size: 98
This key(item_314) has expired
This key(item_315) has expired
2017/07/31 10:31:39 Cache size: 97
This key(item_316) has expired
2017/07/31 10:31:39 Cache size: 97
This key(item_317) has expired
2017/07/31 10:31:39 Cache size: 97
2017/07/31 10:31:40 Cache size: 98
This key(item_318) has expired
This key(item_319) has expired
2017/07/31 10:31:40 Cache size: 97
This key(item_320) has expired
2017/07/31 10:31:40 Cache size: 97
2017/07/31 10:31:40 Cache size: 98
This key(item_321) has expired
2017/07/31 10:31:40 Cache size: 98
This key(item_322) has expired
2017/07/31 10:31:40 Cache size: 98
This key(item_323) has expired
This key(item_324) has expired
2017/07/31 10:31:40 Cache size: 97
2017/07/31 10:31:40 Cache size: 98
This key(item_325) has expired
This key(item_326) has expired
2017/07/31 10:31:40 Cache size: 97
2017/07/31 10:31:41 Cache size: 98
This key(item_327) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_328) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_329) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_330) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_331) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_332) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_333) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_334) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_335) has expired
2017/07/31 10:31:41 Cache size: 98
This key(item_336) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_337) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_338) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_339) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_340) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_341) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_342) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_343) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_344) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_345) has expired
2017/07/31 10:31:42 Cache size: 98
This key(item_346) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_347) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_348) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_349) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_350) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_351) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_352) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_353) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_354) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_355) has expired
2017/07/31 10:31:43 Cache size: 98
This key(item_356) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_357) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_358) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_359) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_360) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_361) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_362) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_363) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_364) has expired
2017/07/31 10:31:44 Cache size: 98
This key(item_365) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_366) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_367) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_368) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_369) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_370) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_371) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_372) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_373) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_374) has expired
2017/07/31 10:31:45 Cache size: 98
This key(item_375) has expired
2017/07/31 10:31:46 Cache size: 97
This key(item_376) has expired
This key(item_377) has expired
2017/07/31 10:31:46 Cache size: 97
2017/07/31 10:31:46 Cache size: 98
This key(item_378) has expired
This key(item_379) has expired
2017/07/31 10:31:46 Cache size: 97
2017/07/31 10:31:46 Cache size: 98
This key(item_380) has expired
2017/07/31 10:31:46 Cache size: 97
This key(item_381) has expired
2017/07/31 10:31:46 Cache size: 98
This key(item_382) has expired
This key(item_383) has expired
2017/07/31 10:31:46 Cache size: 97
2017/07/31 10:31:46 Cache size: 98
This key(item_384) has expired
2017/07/31 10:31:46 Cache size: 98
This key(item_385) has expired
2017/07/31 10:31:47 Cache size: 98
This key(item_386) has expired
This key(item_387) has expired
2017/07/31 10:31:47 Cache size: 97
2017/07/31 10:31:47 Cache size: 98
This key(item_388) has expired
2017/07/31 10:31:47 Cache size: 98
This key(item_389) has expired
2017/07/31 10:31:47 Cache size: 98
2017/07/31 10:31:47 Cache size: 99
2017/07/31 10:31:47 Cache size: 100
2017/07/31 10:31:47 Cache size: 101
2017/07/31 10:31:47 Cache size: 102
2017/07/31 10:31:47 Cache size: 103
2017/07/31 10:31:48 Cache size: 104
2017/07/31 10:31:48 Cache size: 105
I'm planning to use this library as a backend for DNS caching in a proxy server.
After the TTL expires, I plan to fetch a new and possibly updated value from the DNS server. The auto-extending of TTL with Get()
will result in the cache never being updated and potentially having stale values.
I'd like to update an existing cache item in an atomic fashion. Since there is currently no such method I tried to work around it by first calling GetWithTTL()
and then updating the returned item using SetWithTTL()
.
Unfortunately doing this I had a race condition because another Go routine would access/modify it between the Get and Set call. I don't see a workaround because I can't access the mutex.
hi, @ReneKroo
I have encountered some problems with ttlcache, I don't know why?
Can help solve this problem?
thanks.
The panic appears when this program runs below
`
func main() {
cacheAD := ttlcache.NewCache()
cacheAD.SetTTL(time.Second * time.Duration(5))
cacheAD.SetCheckExpirationCallback(func(key string, value interface{}) bool {
v := value.(*int)
log.Printf("key=%v, value=%d\n", key, *v)
return true
})
i := 2
cacheAD.Set("a", &i)
ch := make(chan struct{})
<-ch
}
`
Error message
2018/09/07 15:58:52 key=a, value=2 panic: runtime error: index out of range goroutine 18 [running]: github.com/ReneKroon/ttlcache.(*Cache).startExpirationProcessing(0xc04208c000) D:/workspace-go/busAnalyze/src/github.com/ReneKroon/ttlcache/cache.go:84 +0x4f8 created by github.com/ReneKroon/ttlcache.NewCache D:/workspace-go/busAnalyze/src/github.com/ReneKroon/ttlcache/cache.go:232 +0x11e
I have the expirationCallback and an expire-time of 5 seconds
Let's say I put a key in at 12:00:00
when I keep getting the key from the cache within 5 seconds, the cache expiration message is never shown.
My assumption was, that the expiration was measured from the moment it was put into the cache.
so it would expire at 12:00:05
or... am I doing something wrong?
Use golang heap(http://golang.org/pkg/container/heap/) to handle the expirations.
This is a request for comments / brainstorming...
Currently, ttlCache
expires items if:
Would it be too much of an expansion to have a more dynamic expiry to include a passed in function?
For example, the function could check the content of the item and return a bool
of whether it should be expired.
This could be configured as an option during cache creation to pass the function. The checks could be done in item.isExpiredUnsafe()
A workaround would be to do this outside of the cache by regularly iterating the cache item and running the function on each item and issuing delete if the criteria is met. However, that expiry logic would be nice to offload to the cache.
ExpireCallback is a common callback for two cases:
By using ttlcache.Cache#SkipTTLExtensionOnHit(bool)
you can disable touching the cache entry when using Get
. This offers an additional level over control TTL behaviour.
To offer even more control of this mechanism, I would like to propose to export a touch function as well:
func (cache *Cache) Touch(key string) error {
cache.mutex.Lock()
item, exists := cache.items[key]
if !exists {
return ErrNotFound
}
item.touch()
cache.mutex.Unlock()
return nil
}
Or something similar ๐
This is a lot more convenient that manually getting and setting the item with a new TTL.
panic: runtime error: index out of range [0] with length 0
github.com/ReneKroon/ttlcache/v2.(*Cache).SetWithTTL(0xc0001e8000, 0xc0145aa1e0, 0x20, 0x968da0, 0xc01707c480, 0xd18c2e2800, 0x0, 0x97cc40),
/go/pkg/mod/github.com/!rene!kroon/ttlcache/[email protected]/cache.go:249 +0x3f9,
github.com/ReneKroon/ttlcache/v2.(*Cache).invokeLoader(0xc0001e8000, 0xc0145aa1e0, 0x20, 0x9f1d60, 0xc0004b4088, 0x866700, 0x96a2a0, 0xc00007a0a8),
/go/pkg/mod/github.com/!rene!kroon/ttlcache/[email protected]/cache.go:357 +0xca,
github.com/ReneKroon/ttlcache/v2.(*Cache).GetByLoader(0xc0001e8000, 0xc0145aa1e0, 0x20, 0x0, 0x9, 0x1, 0x3, 0xc0145aa1e
It should return a uint64
that determines how many times an item has been updated. This method may be useful in situations when a task's execution depends on whether the item has changed or not and when due to the duration of another task a transaction/mutex isn't acceptible.
item := cache.Get("key")
version := item.Version()
// long task
if item.Version() == version {
// execute only if the item hasn't been updated during the long task's execution
}
Metrics can be overflow
Since we have a SetWithTTL it would be nice to know how much remain time an item has for expired when we recover it from the cache.
func GetWithTTL(key) (data, ttl, err)
Currently if you register an expiry callback, that callback gets called in one of 3 different scenarios:
Remove
Close
However, you have no way of knowing from within the expiry callback which scenario has occurred.
For context, I have a scenario where I am maintaining a list of items that can be added and removed by users, and if they are removed by users, the cleanup process is already handled as part of handling the users request. However, items need to expire as well and in that case, the users need to be informed that their items have been removed automatically. In the current implementation, if a user removes their own items, they also get informed their item was removed automatically due to the expiration callback firing.
My proposal is for the expiration callback to take an additional argument reason
which can be checked against to see if it was triggered by a Remove, Close or TTL expiry, which then gives me the option of handling it differently for each scenario. Alternatively, having a flag much like the SkipTTLExtensionOnHit
such as ExpireOnTTLOnly
to allow me to strictly support callbacks firing only expirations due to actual expiry rather than removal from the cache would be useful.
is there a limit on no. of keys that can be stored using ttlcache library?
In our service we recently faced increase in response time when ttlcache was being used.
A GoDoc badge would be super nice for each access to docs
Before the stable release of v3, some additional, non-backwards compatible changes could be made. Here is a list of my proposed changes:
On[Noun](fn)
naming pattern (e.g. OnExpiration(fn)
). The provided functions should also be stored in a slice rather than a simple field. A good example of this is bolt's OnCommit.evictionreason_enumer.go
since it seems to add very little value yet creates quite a bit of unidiomatic code noise.Close()
, replace it with Start()
and Stop()
Item
type rather than its fields (applies to Get/Set/event functions).I may have some more ideas later on.
What do you think @ReneKroon?
It should iterate over all cache items and pass each of them into a func that is provided as a parameter:
func (c *Cache[K, V]) Range(fn func(*Item[K, V]) bool) {
// ...
}
The bool return value should indicate whether the iteration should continue or be stopped.
With new version v3 there is currently no way to return loader (either default or getter) error as Get returns only item and there is no way to propagate errors back to caller.
This:
cache = ttlcache.NewCache()
cache.Set("key", "value")
//cache.Remove("key")
count = cache.Count()
fmt.Printf("cache has %d keys\n", count)
prints this:
cache has 1 keys
But if you uncomment the Remove() call, you get this:
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0x76ed00, 0xc820014120)
/software/vertres/installs/go/src/runtime/panic.go:464 +0x3e6
github.com/diegobernardes/ttlcache.priorityQueue.Swap(0x0, 0x0, 0x0, 0x0, 0x0, 0xffffffffffffffff)
/nfs/users/nfs_s/sb10/src/go/src/github.com/diegobernardes/ttlcache/priority_queue.go:54 +0x1f9
github.com/diegobernardes/ttlcache.(_priorityQueue).Swap(0xc8200d8020, 0x0, 0xffffffffffffffff)
:3 +0xaa
container/heap.Remove(0x7f595f9ac750, 0xc8200d8020, 0x0, 0x0, 0x0)
/software/vertres/installs/go/src/container/heap/heap.go:74 +0x6c
github.com/diegobernardes/ttlcache.(_priorityQueue).remove(0xc8200d8020, 0xc8200e0000)
/nfs/users/nfs_s/sb10/src/go/src/github.com/diegobernardes/ttlcache/priority_queue.go:35 +0x56
github.com/diegobernardes/ttlcache.(*Cache).Remove(0xc8200de000, 0x7daeb8, 0x3, 0x6dd860)
/nfs/users/nfs_s/sb10/src/go/src/github.com/diegobernardes/ttlcache/cache.go:167 +0xed
[...]
Currently I have to know (by key) which cache entry I want to remove. My use case is that at some event multiple keys should get invalidated (e.g. all keys with prefix xy). Currently I can maintain my own list of keys using SetNewItemCallback
and SetExpirationReasonCallback
but as I would have to deal with concurrency there as well I would love to see something similar in this library!
Untested draft:
func (cache *Cache) GetKeys() ([]string, error) {
cache.mutex.Lock()
if cache.isShutDown {
cache.mutex.Unlock()
return nil, ErrClosed
}
keys := make([]string, len(cache.items))
i := 0
for k := range cache.items {
keys[i] = k
i++
}
cache.mutex.Unlock()
return keys, nil
}
After closing the cache it's undefined what will happen with additional Get, Set, Remove calls. It should not happen but a best practice Golang practice should be applied.
https://github.com/ReneKroon/ttlcache/blob/f02d66e87ec8b5b94fc799ac83f889b81a1c4043/cache.go#L444
Is there a reason the GetKeys isn't exposed as part of the interface?
I'm using ttlcache but want to test the behaviour of the code using it without relying on actual time passing in a reliable way, and therefore want to use a mock cache. However, I can't make an interface with a compatible SetExpireCallback
method, because it takes a specific, unexported type expireCallback
instead of a plain func(string, interface{})
type.
Ideally I'd either have the SetExpireCallback
method signature use the plain func(string, interface{})
type for it's parameter, though a less pleasant alternative is to have the expireCallback
type exported as ExpireCallback
so that my interface can use it.
It would be helpful to have an instruction how to get the package in the README, like
go get github.com/ReneKroon/ttlcache/v2
cache.SetWithTTL(key, value, 300 * time.Second)
// do something else
cache.SetWithTTL(key, updatedValue, 300 * time.Second)
if this key expires at second 300 * time.Second?
cache.SetWithTTL(key, value, 300 * time.Second)
// do sth else
cache.Set(key, value)
if this key expires at first 300 * time.Second?
doing 30s profiling, it eats 36s of CPU time..
using gops/pprof-cpu
it would be amazing feature if ttlcache would additionally support invalidation of a given cache entry besides the time based expiration.
invalidation could be sync or async (depending of a boolean flag). upon invalidation, the expiration callback could be executed.
Hi, this looks really promising, but has some unexpected behaviour:
cache = ttlcache.NewCache()
cache.SetExpirationCallback(func(key string, value interface{}) {
fmt.Printf("This key(%s) has expired\n", key)
})
cache.SetWithTTL("keyWithTTL", "value", time.Duration(2 * time.Second))
cache.Set("key", "value")
//result = cache.Remove("key")
value, exists = cache.Get("keyWithTTL")
if exists {
fmt.Printf("got %s for keyWithTTL\n", value)
}
count = cache.Count()
fmt.Printf("cache has %d keys\n", count)
<-time.After(3 * time.Second)
value, exists = cache.Get("keyWithTTL")
if exists {
fmt.Printf("got %s for keyWithTTL\n", value)
} else {
fmt.Println("keyWithTTL has gone")
}
count = cache.Count()
fmt.Printf("cache has %d keys\n", count)
The above prints:
got value for keyWithTTL
cache has 2 keys
This key(keyWithTTL) has expired
keyWithTTL has gone
cache has 1 keys
as expected. But if you uncomment the Remove() call, you get:
got value for keyWithTTL
cache has 1 keys
keyWithTTL has gone
cache has 1 keys
so it's in some weird inconsistent state, where you can't get the key, but Count() suggests it's there, and the ExpirationCallback never fired.
Cheers,
it would be great if you could add a license - I could not find anything on that topic, neither in source nor in other files.
TIA
Martin
Hey, I noticed there is no exit case in your Goroutine here:
https://github.com/ReneKroon/ttlcache/blob/49e7d8e56413a8ee1f826b064e7268f6e10ca2d3/cache.go#L52
I was developing an application that start multiple caches as child-struct. But when the parent is removed this function - func (cache *Cache) startExpirationProcessing() - keeps running forever.
Do you perhaps have a way of killing it somewhere in your code ? I like your package and I would love to keep using it, but in the current state I can not :(
Defining a custom loader is great however its usability is pretty low as you have no access to any user_data
that most of the time you need in order to let's say do HTTP(s) requests, file reads etc. This could be solved by being able to add a whatever user_data
object when you are creating the ttlcache.Cache
object. Exposing this user_data
object to the loader along with the key will give the ability to create really powerful loader functions.
Are there any plans to upgrade the project to go1.18 (when it's released) and replace interface{}
types with generic types?
I can open a draft PR with changes made using gotip in the near future if this is something you'd be interested in @ReneKroon.
it would be awesome, if ttlcache could be given a loader function.
Upon a cache miss (key not present in the cache), the cache would call this loader func, and create/load the value for the key, and would put it in the cache with the default global expiration.
It would be nice to have a method that would accept a function and execute it with a new global transaction mutex locked:
func (c *Cache[K, V]) Tx(fn func(*Tx[K, V])) {
c.txMu.Lock()
tx := c.beginTx()
fn(tx)
c.txMu.Unlock()
}
This was addressed in this issue, however, due to some limitations of the previous versions it was closed.
var (
// ErrClosed is raised when operating on a cache where Close() has already been called.
ErrClosed = errors.New("cache already closed")
// ErrNotFound indicates that the requested key is not present in the cache
ErrNotFound = errors.New("key not found")
)
are variables and would be better of as const. However have to check compatibility of that first (assuming it's minor now)
Use case:
I use the cache to capture data i receive over UDP. In some cases, i have competing producers that will send the same information for a Key. I want the first message to win and be the one persisted in the cache and not have further messages overwrite.
Looking at the cache.set() function, it searches for an existing element and overwrites it.
https://github.com/jellydator/ttlcache/blob/master/cache.go#L134-L142
I would like a new option for the cache set on creation to prevent overwrites
cache := ttlcache.New[string, string](
ttlcache.WithTTL[string, string](30 * time.Minute),
ttlcache.WithoutOverwrite(),
)
//Pseudo-code to show the expectation
cache.Set("first", "value1", ttlcache.DefaultTTL)
cache.Set("first", "value2", ttlcache.DefaultTTL)
cache.Set("first", "value3", ttlcache.DefaultTTL)
v:= cache.Get("first").Value()
assert.Equal(t, "value1",v)
example: hit rate
Is there any crash recovery mechanism implemented ?
Jun 17 03:32:09 pro-boqs-app-003 boqs: goroutine 484637918 [running]:
Jun 17 03:32:09 pro-boqs-app-003 boqs: net/http.(*conn).serve.func1(0xc029a32a00)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /usr/local/go/src/net/http/server.go:1769 +0x139
Jun 17 03:32:09 pro-boqs-app-003 boqs: panic(0xc8b580, 0x1517740)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /usr/local/go/src/runtime/panic.go:522 +0x1b5
Jun 17 03:32:09 pro-boqs-app-003 boqs: github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache.priorityQueue.Less(0xc0009cd800, 0x47, 0x100, 0x47, 0x23, 0x5d06ed99)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /go/src/github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache/priority_queue.go:43 +0x16e
Jun 17 03:32:09 pro-boqs-app-003 boqs: container/heap.up(0xef6c60, 0xc000968480, 0x47)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /usr/local/go/src/container/heap/heap.go:93 +0x9f
Jun 17 03:32:09 pro-boqs-app-003 boqs: container/heap.Fix(0xef6c60, 0xc000968480, 0x47)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /usr/local/go/src/container/heap/heap.go:86 +0x94
Jun 17 03:32:09 pro-boqs-app-003 boqs: github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache.(*priorityQueue).update(...)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /go/src/github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache/priority_queue.go:18
Jun 17 03:32:09 pro-boqs-app-003 boqs: github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache.(*Cache).getItem(0xc0001852d0, 0xc0162dbd60, 0x1c, 0x0, 0xed0f58cf0)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /go/src/github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache/cache.go:45 +0xeb
Jun 17 03:32:09 pro-boqs-app-003 boqs: github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache.(*Cache).Get(0xc0001852d0, 0xc0162dbd60, 0x1c, 0x0, 0x0, 0xeeea00)
Jun 17 03:32:09 pro-boqs-app-003 boqs: /go/src/github.com/bolcom/boqs/vendor/github.com/ReneKroon/ttlcache/cache.go:173 +0x50
Jun 17 03:32:09 pro-boqs-app-003 boqs: github.com/bolcom/boqs/internal/dao/cluster.(*PgTopologyCache).SubscribedQueues(0xc000972200, 0xc0162dbd60, 0x1c, 0x183ad9b0, 0xed176645f, 0x152b840, 0xc034089290, 0x3, 0x0, 0x120, ...)
When checkExpireCallback returns true, we should always extend the ttl
of the item, irrespective of the value of skipTtlExtension
.
https://github.com/ReneKroon/ttlcache/blob/f76125ae8c0559130e32b4f47bb3284f7abed9a8/cache.go#L89-L93
I'm trying to move away from patrickmn cache usage in my projects. And I'd like to implement yours where needed. I miss an export and import cache function to persist cache between runs in your cache. Can I add this as a feature request? If you don't have the time and like the idea, I'm willing to help also.
Thanks in advance
From what I can tell, if upon calling a cache.Set(...)
with an item not already in the cache, but the cache is at the configured limit (e.g. 100), only the single oldest item (closest to reaching its TTL) is removed.
Could there be an option we can set on the cache, controlling the amount of items that are removed whenever a cache.Set(...)
is called that would add a new item over the limit?
E.g. if the limit is set to 1000, we're adding an item #1001, and then instead of just deleting 1 item, we can set it to removing the oldest 100 items, reducing the cache back to 901 current items.
I think this would be more efficient, especially for environments where there are a lot of unique items, but most appear rarely, so the oldest items in the cache don't matter as much and can safely be deleted at any time the limit is reached, in one batch.
Coming from the ReneKroon version of this cache, I'm hitting a few issues:
It would be handy, if you could provide a getter function for the cache to retrieve actually retrieve the content, if the cache doesn't contain the requested value like in googles LoadingCache.
It would be useful to also set a maximusSize, like in googles LoadingCache
After running this for a while I noticed it's possible to get a key not found error (ErrNotFound
), even when using a loader function. Repro below.
// Cache sometimes returns key not found under parallel access with a loader function
func TestCache_TestLoaderFunctionParallelKeyAccess(t *testing.T) {
t.Parallel()
cache := NewCache()
cache.SetLoaderFunction(func(key string) (data interface{}, ttl time.Duration, err error) {
time.Sleep(time.Millisecond*300)
return "1", 1*time.Nanosecond, nil
})
wg := sync.WaitGroup{}
errCount := uint64(0)
for i:=0; i<200; i++ {
wg.Add(1)
go func() {
defer wg.Done()
value, found := cache.Get("foo")
if value != "1" || found != nil { // Use an atomic to avoid spamming logs
atomic.AddUint64(&errCount, 1)
}
}()
}
wg.Wait()
assert.Equalf(t, uint64(0), errCount, "expected 0 errs, got %d", errCount)
cache.Close()
}
I spent a while trying to distill this down further, and I think it occurs when:
I think it would be more consistent if the blocked goroutines always got the output of the loaderfunction that they were blocked by. I would probably use singleflight, but there might be a cleaner way to do it.
If you think it's a good idea then I'm happy to put together a PR.
I noticed while playing with this module that I can specify a TTL value from 10
to 50
seconds and everything works great!
However, if I specify a TTL value like 300
, the cache never seems to expire. Apologies of I'm missing something simple here!
Code Snippet:
cache := ttlcache.NewCache()
ttl, err := strconv.Atoi(cacheTTL)
if err != nil {
log.Fatal("Invalid TTL value: ", err)
}
cache.SetTTL(time.Duration(ttl) * time.Second)
expirationCallback := func(key string, _ ttlcache.EvictionReason, _ interface{}) {
log.Info("Cache expired for key: ", key)
}
cache.SetExpirationReasonCallback(expirationCallback)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.