update deps and vendor
This commit is contained in:
@@ -24,6 +24,7 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGn
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -73,6 +74,7 @@ github.com/go-pkgz/jrpc v0.1.0 h1:hNg/IyfEqJcSWOKkuHw0ZwcuGc9TDp7QZREsD2ycmiM=
|
||||
github.com/go-pkgz/jrpc v0.1.0/go.mod h1:JxZsvoBklA50DNhELVJnJ567Rt+KrMH9rR3u515wvE8=
|
||||
github.com/go-pkgz/lcw v0.3.1/go.mod h1:k+PY1CkCMTLXILtFoJOyK65Qqi9rkoTYunFH1vE/C0I=
|
||||
github.com/go-pkgz/lcw v0.4.0/go.mod h1:CSdQRQthxJQ4iDD4wTPPuWFbFdknJzwJ8WXu1nfxb10=
|
||||
github.com/go-pkgz/lcw v0.5.0/go.mod h1:CSdQRQthxJQ4iDD4wTPPuWFbFdknJzwJ8WXu1nfxb10=
|
||||
github.com/go-pkgz/lgr v0.2.2/go.mod h1:hBM1NM/SoYdlrykgdgJWGrZ/TM/XaZIjRbJfx7NkMm8=
|
||||
github.com/go-pkgz/lgr v0.6.2/go.mod h1:hBM1NM/SoYdlrykgdgJWGrZ/TM/XaZIjRbJfx7NkMm8=
|
||||
github.com/go-pkgz/lgr v0.6.3 h1:n9pGk2paBV8w/Y/FVEq5MkwDmP33dnUPKbY4CyyygwM=
|
||||
@@ -273,6 +275,7 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smto
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a h1:Yu34BogBivvmu7SAzHHaB9nZWH5D1C+z3F1jyIaYZSQ=
|
||||
golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -309,6 +312,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -366,6 +370,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
+1
-3
@@ -19,11 +19,9 @@ require (
|
||||
github.com/go-chi/cors v1.0.0
|
||||
github.com/go-chi/render v1.0.1
|
||||
github.com/go-pkgz/auth v0.9.0
|
||||
github.com/go-pkgz/auth/_example v0.0.0-20190722170031-705d3f732438 // indirect
|
||||
github.com/go-pkgz/jrpc v0.1.0
|
||||
github.com/go-pkgz/lcw v0.4.0
|
||||
github.com/go-pkgz/lcw v0.5.0
|
||||
github.com/go-pkgz/lgr v0.6.3
|
||||
github.com/go-pkgz/mongo v1.1.2 // indirect
|
||||
github.com/go-pkgz/repeater v1.1.3
|
||||
github.com/go-pkgz/rest v1.4.1
|
||||
github.com/go-pkgz/syncs v1.1.1
|
||||
|
||||
+7
-37
@@ -5,8 +5,6 @@ cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSR
|
||||
cloud.google.com/go v0.40.0/go.mod h1:Tk58MuI9rbLMKlAjeO/bDnteAx7tX2gJIXw4T5Jwlro=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.44.3 h1:0sMegbmn/8uTwpNkB0q9cLEpZ2W5a6kl+wtBQgPWBJQ=
|
||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.47.0 h1:1JUtpcY9E7+eTospEwWS2QXP3DEn7poB3E2j0jN74mM=
|
||||
@@ -23,18 +21,18 @@ github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8
|
||||
github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U=
|
||||
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/bbolt v1.3.3 h1:n6AiVyVRKQFNb6mJlwESEvvLoDyiTzXX7ORAUlkeBdY=
|
||||
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -58,10 +56,6 @@ github.com/gavv/httpexpect v0.0.0-20180803094507-bdde30871313/go.mod h1:x+9tiU1Y
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
|
||||
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
|
||||
github.com/gavv/monotime v0.0.0-20171021193802-6f8212e8d10d/go.mod h1:vmp8DIyckQMXOPl0AQVHt+7n5h7Gb7hS6CUydiV8QeA=
|
||||
github.com/globalsign/mgo v0.0.0-20180615134936-113d3961e731/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/cors v1.0.0 h1:e6x8k7uWbUwYs+aXDoiUzeQFT6l0cygBYyNhD7/1Tg0=
|
||||
@@ -69,31 +63,16 @@ github.com/go-chi/cors v1.0.0/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VCh
|
||||
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-pkgz/auth v0.4.1/go.mod h1:CWtB8dHmOv+TfF3MUzKwk/YwTLepC2TaDL05A+pFVBM=
|
||||
github.com/go-pkgz/auth v0.8.3 h1:Ll6n2IYN67KFxyI0qdTuk4hXjtUbVdUW4TiR+X36Svc=
|
||||
github.com/go-pkgz/auth v0.8.3/go.mod h1:Ij9y6oBzfsvutSGWSGwh9C4WyU4hOfxB6rTlj4xBwGE=
|
||||
github.com/go-pkgz/auth v0.9.0 h1:1BR+wtbkHzLg4BH1CQUpEO/WzgihrDqzW8XN4g9Pq9g=
|
||||
github.com/go-pkgz/auth v0.9.0/go.mod h1:8Kiold3xA9VUiYZwMyMhwBgiGImZFoL/EmtO9lSIQxo=
|
||||
github.com/go-pkgz/auth/_example v0.0.0-20190722170031-705d3f732438/go.mod h1:rvZtFFkmm3p+E0CHmfUqTGKweCVg2ddsRUrEEPB1iaE=
|
||||
github.com/go-pkgz/jrpc v0.1.0 h1:hNg/IyfEqJcSWOKkuHw0ZwcuGc9TDp7QZREsD2ycmiM=
|
||||
github.com/go-pkgz/jrpc v0.1.0/go.mod h1:JxZsvoBklA50DNhELVJnJ567Rt+KrMH9rR3u515wvE8=
|
||||
github.com/go-pkgz/lcw v0.3.1 h1:PhfB0xNUawLMlx5rXvOTIc7d5LMrr1GM9vIzmG96aUI=
|
||||
github.com/go-pkgz/lcw v0.3.1/go.mod h1:k+PY1CkCMTLXILtFoJOyK65Qqi9rkoTYunFH1vE/C0I=
|
||||
github.com/go-pkgz/lcw v0.4.0 h1:ZK2s7rpHd0OJMLQYgU5cUkZaNYdguhYfuqFbAbJeHso=
|
||||
github.com/go-pkgz/lcw v0.4.0/go.mod h1:CSdQRQthxJQ4iDD4wTPPuWFbFdknJzwJ8WXu1nfxb10=
|
||||
github.com/go-pkgz/lgr v0.2.2/go.mod h1:hBM1NM/SoYdlrykgdgJWGrZ/TM/XaZIjRbJfx7NkMm8=
|
||||
github.com/go-pkgz/lgr v0.6.2 h1:Twf2YIe2J5tg7mKs+IkDDxrDF7GWlTCl/LzqELWjT5o=
|
||||
github.com/go-pkgz/lgr v0.6.2/go.mod h1:hBM1NM/SoYdlrykgdgJWGrZ/TM/XaZIjRbJfx7NkMm8=
|
||||
github.com/go-pkgz/lcw v0.5.0 h1:dSf98y5067zRmBA6fo+gbqLGLy08RGUHoaecwtjDyOE=
|
||||
github.com/go-pkgz/lcw v0.5.0/go.mod h1:CSdQRQthxJQ4iDD4wTPPuWFbFdknJzwJ8WXu1nfxb10=
|
||||
github.com/go-pkgz/lgr v0.6.3 h1:n9pGk2paBV8w/Y/FVEq5MkwDmP33dnUPKbY4CyyygwM=
|
||||
github.com/go-pkgz/lgr v0.6.3/go.mod h1:hBM1NM/SoYdlrykgdgJWGrZ/TM/XaZIjRbJfx7NkMm8=
|
||||
github.com/go-pkgz/mongo v1.0.0/go.mod h1:R9si/F2aJsjz4MUxhzuppIHY8yLV3YCeuCpgcI50cu4=
|
||||
github.com/go-pkgz/mongo v1.1.2 h1:2Vqn3CWQJkkx4gxxDiQUitAW2FN/CH26lKHkipmpKcc=
|
||||
github.com/go-pkgz/mongo v1.1.2/go.mod h1:0NkWnzpiUxoL5fYZuttCtJrpC67oNDidfYxcdPqHTf0=
|
||||
github.com/go-pkgz/repeater v1.1.2 h1:OxTyUMdEGiN4jRk5g3HHWQ6o4GDezjCLwpmDa/On+mU=
|
||||
github.com/go-pkgz/repeater v1.1.2/go.mod h1:QfNR/a+xqjs+f9wSxWqOQlw9aQhmKlUaSwXCiZ+Ko2w=
|
||||
github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE=
|
||||
github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw=
|
||||
github.com/go-pkgz/rest v1.2.0/go.mod h1:COazNj35u3RXAgQNBr6neR599tYP3URiOpsu9p0rOtk=
|
||||
github.com/go-pkgz/rest v1.4.1 h1:DmaVLPH2O7yLehrWOW0uz01d2mVHz9fBR/iuTiPRzaw=
|
||||
github.com/go-pkgz/rest v1.4.1/go.mod h1:COazNj35u3RXAgQNBr6neR599tYP3URiOpsu9p0rOtk=
|
||||
github.com/go-pkgz/syncs v1.1.1 h1:jWN+y6FS/Xe+8z4l3QMbSnODGyaxDHGojIS+wyKIjxg=
|
||||
@@ -116,10 +95,12 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
|
||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@@ -222,8 +203,6 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:X
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
@@ -275,6 +254,7 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn
|
||||
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
|
||||
github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
|
||||
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 h1:1b6PAtenNyhsmo/NKXVe34h7JEZKva1YB/ne7K7mqKM=
|
||||
github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
@@ -288,8 +268,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90Pveol
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586 h1:7KByu05hhLed2MO29w7p1XfZvZ13m8mub3shuVftRs0=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -297,13 +275,10 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
|
||||
golang.org/x/image v0.0.0-20181116024801-cd38e8056d9b/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff h1:+2zgJKVDVAz/BWSsuniCmU1kLCjL88Z8/kv39xCI9NQ=
|
||||
golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20190823064033-3a9bac650e44 h1:1/e6LjNi7iqpDTz8tCLSKoR5dqrX4C3ub4H31JJZM4U=
|
||||
golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -325,7 +300,6 @@ golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190107210223-45ffb0cd1ba0/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@@ -337,12 +311,9 @@ golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
|
||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a h1:Yu34BogBivvmu7SAzHHaB9nZWH5D1C+z3F1jyIaYZSQ=
|
||||
golang.org/x/net v0.0.0-20191027093000-83d349e8ac1a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -357,7 +328,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190109145017-48ac38b7c8cb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.12.x"
|
||||
|
||||
install: true
|
||||
|
||||
go_import_path: github.com/go-pkgz/lcw
|
||||
|
||||
before_install:
|
||||
- export TZ=America/Chicago
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.19.1
|
||||
- go get github.com/mattn/goveralls
|
||||
- export PATH=$(pwd)/bin:$PATH
|
||||
|
||||
script:
|
||||
- GO111MODULE=on go get ./...
|
||||
- GO111MODULE=on go mod vendor
|
||||
- GO111MODULE=on go test -v -mod=vendor -covermode=count -coverprofile=profile.cov ./... || travis_terminate 1;
|
||||
- golangci-lint run || travis_terminate 1;
|
||||
- $GOPATH/bin/goveralls -coverprofile=profile.cov -service=travis-ci
|
||||
+10
-1
@@ -1,4 +1,4 @@
|
||||
# Loading Cache Wrapper [](https://travis-ci.org/go-pkgz/lcw) [](https://coveralls.io/github/go-pkgz/lcw?branch=master) [](https://godoc.org/github.com/go-pkgz/lcw)
|
||||
# Loading Cache Wrapper [](https://github.com/go-pkgz/lcw/actions) [](https://coveralls.io/github/go-pkgz/lcw?branch=master) [](https://godoc.org/github.com/go-pkgz/lcw)
|
||||
|
||||
|
||||
The library adds a thin layer on top of [lru cache](https://github.com/hashicorp/golang-lru) and [patrickmn/go-cache](https://github.com/patrickmn/go-cache).
|
||||
@@ -54,6 +54,15 @@ Cache can be created with URIs:
|
||||
- `redis://10.0.0.1:1234?db=16&password=qwerty&network=tcp4&dial_timeout=1s&read_timeout=5s&write_timeout=3s` - create redis cache
|
||||
- `nop://` - create Nop cache
|
||||
|
||||
## Scoped cache
|
||||
|
||||
`Scache` provides a wrapper on top of all implementations of `LoadingCache` with a number of special features:
|
||||
|
||||
1. Key is not a string but a composed type made from partition, key-id and list of scopes (tags).
|
||||
1. Value type limited to `[]byte`
|
||||
1. Added `Flush` method for scoped/tagged invalidation of multiple records in a given partition
|
||||
1. Simplified interface with Get, Stat and Flush only.
|
||||
|
||||
## Details
|
||||
|
||||
- All byte-size limits (MaxCacheSize and MaxValSize) only work for values implementing `lcw.Sizer` interface.
|
||||
|
||||
+4
@@ -27,6 +27,7 @@ type LoadingCache interface {
|
||||
Delete(key string) // delete by key
|
||||
Purge() // clear cache
|
||||
Stat() CacheStat // cache stats
|
||||
Keys() []string // list of all keys
|
||||
}
|
||||
|
||||
// CacheStat represent stats values
|
||||
@@ -67,6 +68,9 @@ func (n *Nop) Purge() {}
|
||||
// Delete does nothing for nop cache
|
||||
func (n *Nop) Delete(key string) {}
|
||||
|
||||
// Delete does nothing for nop cache
|
||||
func (n *Nop) Keys() []string { return nil }
|
||||
|
||||
// Stat always 0s for nop cache
|
||||
func (n *Nop) Stat() CacheStat {
|
||||
return CacheStat{}
|
||||
|
||||
+9
@@ -102,6 +102,15 @@ func (c *ExpirableCache) Delete(key string) {
|
||||
c.backend.Delete(key)
|
||||
}
|
||||
|
||||
func (c *ExpirableCache) Keys() (res []string) {
|
||||
items := c.backend.Items()
|
||||
res = make([]string, 0, len(items))
|
||||
for key := range items {
|
||||
res = append(res, key)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Stat returns cache statistics
|
||||
func (c *ExpirableCache) Stat() CacheStat {
|
||||
return CacheStat{
|
||||
|
||||
+9
@@ -104,6 +104,15 @@ func (c *LruCache) Delete(key string) {
|
||||
c.backend.Remove(key)
|
||||
}
|
||||
|
||||
func (c *LruCache) Keys() (res []string) {
|
||||
keys := c.backend.Keys()
|
||||
res = make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
res = append(res, key.(string))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Stat returns cache statistics
|
||||
func (c *LruCache) Stat() CacheStat {
|
||||
return CacheStat{
|
||||
|
||||
+5
@@ -103,6 +103,11 @@ func (c *RedisCache) Delete(key string) {
|
||||
c.backend.Del(key)
|
||||
}
|
||||
|
||||
// Keys gets all keys for the cache
|
||||
func (c *RedisCache) Keys() (res []string) {
|
||||
return c.backend.Keys("*").Val()
|
||||
}
|
||||
|
||||
// Stat returns cache statistics
|
||||
func (c *RedisCache) Stat() CacheStat {
|
||||
return CacheStat{
|
||||
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
package lcw
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Scache wraps LoadingCache with partitions (sub-system), and scopes.
|
||||
// Simplified interface with just 3 funcs - Get, Flush and Stats
|
||||
type Scache struct {
|
||||
lc LoadingCache
|
||||
}
|
||||
|
||||
// NewScache creates Scache on top of LoadingCache
|
||||
func NewScache(lc LoadingCache) *Scache {
|
||||
return &Scache{lc: lc}
|
||||
}
|
||||
|
||||
func (m *Scache) Get(key Key, fn func() ([]byte, error)) (data []byte, err error) {
|
||||
keyStr := key.String()
|
||||
val, err := m.lc.Get(keyStr, func() (value Value, e error) {
|
||||
return fn()
|
||||
})
|
||||
return val.([]byte), err
|
||||
}
|
||||
|
||||
// Stat delegates the call to the underlying cache backend
|
||||
func (m *Scache) Stat() CacheStat {
|
||||
return m.lc.Stat()
|
||||
}
|
||||
|
||||
// Flush clears cache and calls postFlushFn async
|
||||
func (m *Scache) Flush(req FlusherRequest) {
|
||||
|
||||
if len(req.scopes) == 0 {
|
||||
m.lc.Purge()
|
||||
return
|
||||
}
|
||||
|
||||
// check if fullKey has matching scopes
|
||||
inScope := func(fullKey string) bool {
|
||||
key, err := parseKey(fullKey)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, s := range req.scopes {
|
||||
for _, ks := range key.scopes {
|
||||
if ks == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, k := range m.lc.Keys() {
|
||||
if inScope(k) {
|
||||
m.lc.Delete(k) // Keys() returns copy of cache's key, safe to remove directly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Key for scoped cache. Created foe given partition (can be empty) and set with ID and Scopes.
|
||||
// example: k := NewKey("sys1").ID(postID).Scopes("last_posts", customer_id)
|
||||
type Key struct {
|
||||
id string // the primary part of the key, i.e. usual cache's key
|
||||
partition string // optional id for a subsystem or cache partition
|
||||
scopes []string // list of scopes to use in invalidation
|
||||
}
|
||||
|
||||
// NewKey makes base key for given partition. Partition can be omitted.
|
||||
func NewKey(partition ...string) Key {
|
||||
if len(partition) == 0 {
|
||||
return Key{partition: ""}
|
||||
}
|
||||
return Key{partition: partition[0]}
|
||||
}
|
||||
|
||||
// ID sets key id
|
||||
func (k Key) ID(id string) Key {
|
||||
k.id = id
|
||||
return k
|
||||
}
|
||||
|
||||
// Scopes of the key
|
||||
func (k Key) Scopes(scopes ...string) Key {
|
||||
k.scopes = scopes
|
||||
return k
|
||||
}
|
||||
|
||||
// String makes full string key from primary key, partition and scopes
|
||||
// key string made as <partition>@@<id>@@<scope1>$$<scope2>....
|
||||
func (k Key) String() string {
|
||||
bld := strings.Builder{}
|
||||
bld.WriteString(k.partition)
|
||||
bld.WriteString("@@")
|
||||
bld.WriteString(k.id)
|
||||
bld.WriteString("@@")
|
||||
bld.WriteString(strings.Join(k.scopes, "$$"))
|
||||
return bld.String()
|
||||
}
|
||||
|
||||
// parseKey gets compound key string created by Key func and split it to the actual key, partition and scopes
|
||||
// key string made as <partition>@@<id>@@<scope1>$$<scope2>....
|
||||
func parseKey(keyStr string) (Key, error) {
|
||||
elems := strings.Split(keyStr, "@@")
|
||||
if len(elems) != 3 {
|
||||
return Key{}, errors.Errorf("can't parse cache key %s, invalid number of segments %d", keyStr, len(elems))
|
||||
}
|
||||
|
||||
scopes := strings.Split(elems[2], "$$")
|
||||
if len(scopes) == 1 && scopes[0] == "" {
|
||||
scopes = []string{}
|
||||
}
|
||||
key := Key{
|
||||
partition: elems[0],
|
||||
id: elems[1],
|
||||
scopes: scopes,
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// FlusherRequest used as input for cache.Flush
|
||||
type FlusherRequest struct {
|
||||
partition string
|
||||
scopes []string
|
||||
}
|
||||
|
||||
// Flusher makes new FlusherRequest with empty scopes
|
||||
func Flusher(partition string) FlusherRequest {
|
||||
res := FlusherRequest{partition: partition}
|
||||
return res
|
||||
}
|
||||
|
||||
// Scopes adds scopes to FlusherRequest
|
||||
func (f FlusherRequest) Scopes(scopes ...string) FlusherRequest {
|
||||
f.scopes = scopes
|
||||
return f
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
|
||||
## Cache wrapper for web applications.
|
||||
|
||||
The primary goal is to simplify caching of responses.
|
||||
|
||||
Adds guava-style loading cache and support of scopes for partial flushes.
|
||||
Provides in-memory `NewMemoryCache` on top of [hashicorp/golang-lru]("https://github.com/hashicorp/golang-lru") and
|
||||
defines basic interface for other implementations.
|
||||
|
||||
In addition to `Get` and `Flush` methods, memory cache also support limits for a single value size, number of keys and total memory utilization. `PostFlushFn` adds ability to call a function on flush completion.
|
||||
|
||||
## Install and update
|
||||
|
||||
`go get -u github.com/go-pkgz/rest/cache`
|
||||
|
||||
## Technical details
|
||||
|
||||
- Cache keeps data in a simple key:value format.
|
||||
- Key is a type, created with `Key(site_id)` where `site_id` represents independent bucket in the cache. For simple cases can be set to an empty string.
|
||||
- Particular key set by `Key.ID(string)`
|
||||
- Key may contain optional scopes (list of string). They not affect retrieval and used for partial (scoped) invalidation only.
|
||||
- Cache is safe for concurrent use.
|
||||
- Value is []byte.
|
||||
- `Get` method returns from the cache if the key already in. Overwise executes passed function and saves results.
|
||||
- Special fake implementation `cache.Nop` satisfies `LoadingCache` interface and can be used to disable any caching
|
||||
|
||||
## Usage
|
||||
|
||||
```golang
|
||||
// create in-memory cache with max keys=50, total (max) size=2000 and max cached size of a record = 200
|
||||
lc, err := cache.NewMemoryCache(cache.MaxKeys(50), cacheMaxCacheSize(2000), cache.MaxValSize(200))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
...
|
||||
|
||||
// load cached value for key1. Call func if not cached yet or evicted
|
||||
res, err = lc.Get(cache.NewKey("site1").ID("key1").Scopes("scope1"), func() ([]byte, error) {
|
||||
return []byte("1234567890"), nil
|
||||
})
|
||||
|
||||
lc.Flush(cache.Flusher("site1").Scopes("scope1")) // invalidate cache for scope1
|
||||
```
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
// Package cache implements a wrapper on top of hashicorp/golang-lru with guava-style loader func.
|
||||
// In addition for Get (i.e. load from cache if found and put to cache if absent) it adds a Key struct
|
||||
// with record ID, site ID and invalidation scopes. Scopes used to evict matching records.
|
||||
// Additional limits added for total cache size, mac number of keys and max size of the value. If exceeded it won't
|
||||
// put to cache but will call loader func.
|
||||
// Usually the cache involved on []byte response level, i.e. post-marshaling right before response's send.
|
||||
package cache
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// LoadingCache defines interface for caching
|
||||
type LoadingCache interface {
|
||||
Get(key Key, fn func() ([]byte, error)) (data []byte, err error) // load from cache if found or put to cache and return
|
||||
Flush(req FlusherRequest) // evict matched records
|
||||
}
|
||||
|
||||
type cacheWithOpts interface {
|
||||
LoadingCache
|
||||
setMaxValSize(max int) error // max value size, in bytes
|
||||
setMaxKeys(max int) error // max number of keys
|
||||
setMaxCacheSize(max int64) error // max cache size (total values) in bytes
|
||||
setPostFlushFn(postFlushFn func()) error // optional callback after flush
|
||||
}
|
||||
|
||||
// Key for cache
|
||||
type Key struct {
|
||||
id string
|
||||
siteID string
|
||||
scopes []string
|
||||
}
|
||||
|
||||
// NewKey makes keys for site
|
||||
func NewKey(site string) Key {
|
||||
res := Key{siteID: site}
|
||||
return res
|
||||
}
|
||||
|
||||
// ID sets key id
|
||||
func (k Key) ID(id string) Key {
|
||||
k.id = id
|
||||
return k
|
||||
}
|
||||
|
||||
// Scopes of the key
|
||||
func (k Key) Scopes(scopes ...string) Key {
|
||||
k.scopes = scopes
|
||||
return k
|
||||
}
|
||||
|
||||
// Merge makes full string key from primary key and scopes
|
||||
func (k Key) Merge() string {
|
||||
return strings.Join(k.scopes, "$$") + "@@" + k.id + "@@" + k.siteID
|
||||
}
|
||||
|
||||
// ParseKey gets compound key created by Key func and split it to the actual key and scopes
|
||||
func ParseKey(fullKey string) (Key, error) {
|
||||
elems := strings.Split(fullKey, "@@")
|
||||
if len(elems) != 3 {
|
||||
return Key{}, errors.Errorf("can't parse cache key %s", fullKey)
|
||||
}
|
||||
scopes := strings.Split(elems[0], "$$")
|
||||
if len(scopes) == 1 && scopes[0] == "" {
|
||||
scopes = []string{}
|
||||
}
|
||||
key := Key{
|
||||
scopes: scopes,
|
||||
id: elems[1],
|
||||
siteID: elems[2],
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// FlusherRequest used as input for cache.Flush
|
||||
type FlusherRequest struct {
|
||||
siteID string
|
||||
scopes []string
|
||||
}
|
||||
|
||||
// Flusher makes new FlusherRequest with empty scopes
|
||||
func Flusher(siteID string) FlusherRequest {
|
||||
res := FlusherRequest{siteID: siteID}
|
||||
return res
|
||||
}
|
||||
|
||||
// Scopes adds scopes to FlusherRequest
|
||||
func (f FlusherRequest) Scopes(scopes ...string) FlusherRequest {
|
||||
f.scopes = scopes
|
||||
return f
|
||||
}
|
||||
|
||||
// Nop does nothing for caching, passing fn call only
|
||||
type Nop struct{}
|
||||
|
||||
// Get calls fn, no actual caching
|
||||
func (n *Nop) Get(key Key, fn func() ([]byte, error)) (data []byte, err error) {
|
||||
return fn()
|
||||
}
|
||||
|
||||
// Flush does nothing for NoopCache
|
||||
func (n *Nop) Flush(req FlusherRequest) {}
|
||||
-142
@@ -1,142 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// memoryCache implements LoadingCache interface on top of cache.Cache (go-cache)
|
||||
type memoryCache struct {
|
||||
bytesCache *lru.Cache
|
||||
postFlushFn func()
|
||||
maxKeys int
|
||||
maxValueSize int
|
||||
maxCacheSize int64
|
||||
currentSize int64
|
||||
}
|
||||
|
||||
// NewMemoryCache makes memoryCache implementation
|
||||
func NewMemoryCache(options ...Option) (LoadingCache, error) {
|
||||
|
||||
res := memoryCache{
|
||||
postFlushFn: func() {},
|
||||
maxKeys: 1000,
|
||||
maxValueSize: 0,
|
||||
}
|
||||
for _, opt := range options {
|
||||
if err := opt(&res); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to set cache option")
|
||||
}
|
||||
}
|
||||
|
||||
onEvicted := func(key interface{}, value interface{}) {
|
||||
size := len(value.([]byte))
|
||||
atomic.AddInt64(&res.currentSize, -1*int64(size))
|
||||
}
|
||||
|
||||
var err error
|
||||
// OnEvicted called automatically for expired and manually deleted
|
||||
if res.bytesCache, err = lru.NewWithEvict(res.maxKeys, onEvicted); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to make cache")
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
// Get is loading cache method to get value by key or load via fn if not found
|
||||
func (m *memoryCache) Get(key Key, fn func() ([]byte, error)) (data []byte, err error) {
|
||||
mkey := key.Merge()
|
||||
if b, ok := m.bytesCache.Get(mkey); ok {
|
||||
return b.([]byte), nil
|
||||
}
|
||||
|
||||
if data, err = fn(); err != nil {
|
||||
return data, err
|
||||
}
|
||||
if m.allowed(data) {
|
||||
m.bytesCache.Add(mkey, data)
|
||||
atomic.AddInt64(&m.currentSize, int64(len(data)))
|
||||
|
||||
if m.maxCacheSize > 0 && atomic.LoadInt64(&m.currentSize) > m.maxCacheSize {
|
||||
for atomic.LoadInt64(&m.currentSize) > m.maxCacheSize {
|
||||
m.bytesCache.RemoveOldest()
|
||||
}
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Flush clears cache and calls postFlushFn async
|
||||
func (m *memoryCache) Flush(req FlusherRequest) {
|
||||
|
||||
if len(req.scopes) == 0 {
|
||||
m.bytesCache.Purge()
|
||||
go m.postFlushFn()
|
||||
return
|
||||
}
|
||||
|
||||
// check if fullKey has matching scopes
|
||||
inScope := func(fullKey string) bool {
|
||||
key, err := ParseKey(fullKey)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, s := range req.scopes {
|
||||
for _, ks := range key.scopes {
|
||||
if ks == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
for _, k := range m.bytesCache.Keys() {
|
||||
key := k.(string)
|
||||
if inScope(key) {
|
||||
m.bytesCache.Remove(key) // Keys() returns copy of cache's key, safe to remove directly
|
||||
}
|
||||
}
|
||||
|
||||
if m.postFlushFn != nil {
|
||||
go m.postFlushFn()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *memoryCache) allowed(data []byte) bool {
|
||||
if m.maxValueSize > 0 && len(data) >= m.maxValueSize {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *memoryCache) setMaxValSize(max int) error {
|
||||
m.maxValueSize = max
|
||||
if max <= 0 {
|
||||
return errors.Errorf("negative size for MaxValSize, %d", max)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryCache) setMaxKeys(max int) error {
|
||||
m.maxKeys = max
|
||||
if max <= 0 {
|
||||
return errors.Errorf("negative size for MaxKeys, %d", max)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryCache) setMaxCacheSize(max int64) error {
|
||||
m.maxCacheSize = max
|
||||
if max <= 0 {
|
||||
return errors.Errorf("negative size or MaxCacheSize, %d", max)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryCache) setPostFlushFn(postFlushFn func()) error {
|
||||
m.postFlushFn = postFlushFn
|
||||
return nil
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package cache
|
||||
|
||||
// Option func type
|
||||
type Option func(lc cacheWithOpts) error
|
||||
|
||||
// MaxValSize functional option defines the largest value's size allowed to be cached
|
||||
// By default it is 0, which means unlimited.
|
||||
func MaxValSize(max int) Option {
|
||||
return func(lc cacheWithOpts) error {
|
||||
return lc.setMaxValSize(max)
|
||||
}
|
||||
}
|
||||
|
||||
// MaxKeys functional option defines how many keys to keep.
|
||||
// By default it is 0, which means unlimited.
|
||||
func MaxKeys(max int) Option {
|
||||
return func(lc cacheWithOpts) error {
|
||||
return lc.setMaxKeys(max)
|
||||
}
|
||||
}
|
||||
|
||||
// MaxCacheSize functional option defines the total size of cached data.
|
||||
// By default it is 0, which means unlimited.
|
||||
func MaxCacheSize(max int64) Option {
|
||||
return func(lc cacheWithOpts) error {
|
||||
return lc.setMaxCacheSize(max)
|
||||
}
|
||||
}
|
||||
|
||||
// PostFlushFn functional option defines how callback function called after each Flush.
|
||||
func PostFlushFn(postFlushFn func()) Option {
|
||||
return func(lc cacheWithOpts) error {
|
||||
return lc.setPostFlushFn(postFlushFn)
|
||||
}
|
||||
}
|
||||
Vendored
+1
-2
@@ -37,7 +37,7 @@ github.com/go-pkgz/auth/provider/sender
|
||||
github.com/go-pkgz/auth/token
|
||||
# github.com/go-pkgz/jrpc v0.1.0
|
||||
github.com/go-pkgz/jrpc
|
||||
# github.com/go-pkgz/lcw v0.4.0
|
||||
# github.com/go-pkgz/lcw v0.5.0
|
||||
github.com/go-pkgz/lcw
|
||||
# github.com/go-pkgz/lgr v0.6.3
|
||||
github.com/go-pkgz/lgr
|
||||
@@ -46,7 +46,6 @@ github.com/go-pkgz/repeater
|
||||
github.com/go-pkgz/repeater/strategy
|
||||
# github.com/go-pkgz/rest v1.4.1
|
||||
github.com/go-pkgz/rest
|
||||
github.com/go-pkgz/rest/cache
|
||||
github.com/go-pkgz/rest/logger
|
||||
# github.com/go-pkgz/syncs v1.1.1
|
||||
github.com/go-pkgz/syncs
|
||||
|
||||
Reference in New Issue
Block a user