diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bd11cc1..0903fdbf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,11 +10,12 @@ and this project adheres to
## [Unreleased]
### Added
+- Optimistic cache ([#2145]).
- New possible value of `6h` for `querylog_interval` setting ([#2504]).
- Blocking access using client IDs ([#2624], [#3162]).
- `source` directives support in `/etc/network/interfaces` on Linux ([#3257]).
@@ -53,11 +54,6 @@ and this project adheres to
### Deprecated
-
-
- Go 1.16 support. v0.108.0 will require at least Go 1.17 to build.
### Fixed
@@ -83,6 +79,7 @@ released by then.
[#1381]: https://github.com/AdguardTeam/AdGuardHome/issues/1381
[#1691]: https://github.com/AdguardTeam/AdGuardHome/issues/1691
[#2141]: https://github.com/AdguardTeam/AdGuardHome/issues/2141
+[#2145]: https://github.com/AdguardTeam/AdGuardHome/issues/2145
[#2280]: https://github.com/AdguardTeam/AdGuardHome/issues/2280
[#2439]: https://github.com/AdguardTeam/AdGuardHome/issues/2439
[#2441]: https://github.com/AdguardTeam/AdGuardHome/issues/2441
diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 8254c9ea..246f19c7 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -597,6 +597,8 @@
"cache_ttl_min_override_desc": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses",
"cache_ttl_max_override_desc": "Set a maximum time-to-live value (seconds) for entries in the DNS cache",
"ttl_cache_validation": "Minimum cache TTL value must be less than or equal to the maximum value",
+ "cache_optimistic": "Optimistic",
+ "cache_optimistic_desc": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.",
"filter_category_general": "General",
"filter_category_security": "Security",
"filter_category_regional": "Regional",
diff --git a/client/src/components/Settings/Dns/Cache/Form.js b/client/src/components/Settings/Dns/Cache/Form.js
index 9a13ec63..5b0fe6a2 100644
--- a/client/src/components/Settings/Dns/Cache/Form.js
+++ b/client/src/components/Settings/Dns/Cache/Form.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Field, reduxForm } from 'redux-form';
import { Trans, useTranslation } from 'react-i18next';
import { shallowEqual, useSelector } from 'react-redux';
-import { renderInputField, toNumber } from '../../../../helpers/form';
+import { renderInputField, toNumber, CheckboxField } from '../../../../helpers/form';
import { CACHE_CONFIG_FIELDS, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants';
import { replaceZeroWithEmptyString } from '../../../../helpers/helpers';
@@ -47,27 +47,48 @@ const Form = ({
}) =>
-
{t(title)}
+
+ {t(title)}
+
{t(description)}
)}
- {minExceedsMax
- && {t('ttl_cache_validation')} }
+ {minExceedsMax && (
+
+ {t('ttl_cache_validation')}
+
+ )}
+
+
{
const { t } = useTranslation();
const dispatch = useDispatch();
const {
- cache_size, cache_ttl_max, cache_ttl_min,
+ cache_size, cache_ttl_max, cache_ttl_min, cache_optimistic,
} = useSelector((state) => state.dnsConfig, shallowEqual);
const handleFormSubmit = (values) => {
@@ -31,6 +31,7 @@ const CacheConfig = () => {
cache_size: replaceZeroWithEmptyString(cache_size),
cache_ttl_max: replaceZeroWithEmptyString(cache_ttl_max),
cache_ttl_min: replaceZeroWithEmptyString(cache_ttl_min),
+ cache_optimistic,
}}
onSubmit={handleFormSubmit}
/>
diff --git a/internal/dnsforward/config.go b/internal/dnsforward/config.go
index 213f6221..5a7c81d7 100644
--- a/internal/dnsforward/config.go
+++ b/internal/dnsforward/config.go
@@ -101,6 +101,8 @@ type FilteringConfig struct {
CacheSize uint32 `yaml:"cache_size"` // DNS cache size (in bytes)
CacheMinTTL uint32 `yaml:"cache_ttl_min"` // override TTL value (minimum) received from upstream server
CacheMaxTTL uint32 `yaml:"cache_ttl_max"` // override TTL value (maximum) received from upstream server
+ // CacheOptimistic defines if optimistic cache mechanism should be used.
+ CacheOptimistic bool `yaml:"cache_optimistic"`
// Other settings
// --
@@ -210,6 +212,7 @@ func (s *Server) createProxyConfig() (proxy.Config, error) {
RefuseAny: s.conf.RefuseAny,
CacheMinTTL: s.conf.CacheMinTTL,
CacheMaxTTL: s.conf.CacheMaxTTL,
+ CacheOptimistic: s.conf.CacheOptimistic,
UpstreamConfig: s.conf.UpstreamConfig,
BeforeRequestHandler: s.beforeRequestHandler,
RequestHandler: s.handleDNSRequest,
diff --git a/internal/dnsforward/http.go b/internal/dnsforward/http.go
index 3f2ccf55..f72af780 100644
--- a/internal/dnsforward/http.go
+++ b/internal/dnsforward/http.go
@@ -41,6 +41,7 @@ type dnsConfig struct {
CacheSize *uint32 `json:"cache_size"`
CacheMinTTL *uint32 `json:"cache_ttl_min"`
CacheMaxTTL *uint32 `json:"cache_ttl_max"`
+ CacheOptimistic *bool `json:"cache_optimistic"`
ResolveClients *bool `json:"resolve_clients"`
UsePrivateRDNS *bool `json:"use_private_ptr_resolvers"`
LocalPTRUpstreams *[]string `json:"local_ptr_upstreams"`
@@ -64,6 +65,7 @@ func (s *Server) getDNSConfig() dnsConfig {
cacheSize := s.conf.CacheSize
cacheMinTTL := s.conf.CacheMinTTL
cacheMaxTTL := s.conf.CacheMaxTTL
+ cacheOptimistic := s.conf.CacheOptimistic
resolveClients := s.conf.ResolveClients
usePrivateRDNS := s.conf.UsePrivateRDNS
localPTRUpstreams := aghstrings.CloneSliceOrEmpty(s.conf.LocalPTRResolvers)
@@ -89,6 +91,7 @@ func (s *Server) getDNSConfig() dnsConfig {
CacheSize: &cacheSize,
CacheMinTTL: &cacheMinTTL,
CacheMaxTTL: &cacheMaxTTL,
+ CacheOptimistic: &cacheOptimistic,
UpstreamMode: &upstreamMode,
ResolveClients: &resolveClients,
UsePrivateRDNS: &usePrivateRDNS,
@@ -283,6 +286,11 @@ func (s *Server) setConfigRestartable(dc dnsConfig) (restart bool) {
restart = true
}
+ if dc.CacheOptimistic != nil {
+ s.conf.CacheOptimistic = *dc.CacheOptimistic
+ restart = true
+ }
+
return restart
}
diff --git a/internal/dnsforward/http_test.go b/internal/dnsforward/http_test.go
index 99fece08..582317ec 100644
--- a/internal/dnsforward/http_test.go
+++ b/internal/dnsforward/http_test.go
@@ -48,7 +48,7 @@ func loadTestData(t *testing.T, casesFileName string, cases interface{}) {
const jsonExt = ".json"
-func TestDNSForwardHTTTP_handleGetConfig(t *testing.T) {
+func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
filterConf := &filtering.Config{
SafeBrowsingEnabled: true,
SafeBrowsingCacheSize: 1000,
@@ -123,7 +123,7 @@ func TestDNSForwardHTTTP_handleGetConfig(t *testing.T) {
}
}
-func TestDNSForwardHTTTP_handleSetConfig(t *testing.T) {
+func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
filterConf := &filtering.Config{
SafeBrowsingEnabled: true,
SafeBrowsingCacheSize: 1000,
diff --git a/internal/dnsforward/testdata/TestDNSForwardHTTTP_handleGetConfig.json b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json
similarity index 95%
rename from internal/dnsforward/testdata/TestDNSForwardHTTTP_handleGetConfig.json
rename to internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json
index 4d810c94..538865c5 100644
--- a/internal/dnsforward/testdata/TestDNSForwardHTTTP_handleGetConfig.json
+++ b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleGetConfig.json
@@ -23,6 +23,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -51,6 +52,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -79,6 +81,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
diff --git a/internal/dnsforward/testdata/TestDNSForwardHTTTP_handleSetConfig.json b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json
similarity index 95%
rename from internal/dnsforward/testdata/TestDNSForwardHTTTP_handleSetConfig.json
rename to internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json
index 2d2e34b5..b594029c 100644
--- a/internal/dnsforward/testdata/TestDNSForwardHTTTP_handleSetConfig.json
+++ b/internal/dnsforward/testdata/TestDNSForwardHTTP_handleSetConfig.json
@@ -30,6 +30,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -62,6 +63,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -95,6 +97,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -128,6 +131,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -161,6 +165,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -194,6 +199,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -227,6 +233,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -260,6 +267,7 @@
"cache_size": 1024,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -293,6 +301,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -326,6 +335,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -361,6 +371,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -396,6 +407,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -430,6 +442,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -463,6 +476,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
@@ -498,6 +512,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": [
@@ -533,6 +548,7 @@
"cache_size": 0,
"cache_ttl_min": 0,
"cache_ttl_max": 0,
+ "cache_optimistic": false,
"resolve_clients": false,
"use_private_ptr_resolvers": false,
"local_ptr_upstreams": []
diff --git a/openapi/CHANGELOG.md b/openapi/CHANGELOG.md
index 3e2f0577..9a70bb9a 100644
--- a/openapi/CHANGELOG.md
+++ b/openapi/CHANGELOG.md
@@ -4,6 +4,14 @@
## v0.107: API changes
+### The new field `"cache_optimistic"` in DNS configuration
+
+* The new optional field `"cache_optimistic"` in `POST /control/dns_config`
+ method makes AdGuard Home use or not use the optimistic cache mechanism.
+
+* The new field `"cache_optimistic"` in `GET /control/dns_info` method is true
+ if AdGuard Home uses the optimistic cache mechanism.
+
### New possible value of `"interval"` field in `QueryLogConfig`
* The value of `"interval"` field in `POST /control/querylog_config` and `GET
diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml
index f2fdca6b..44c3c599 100644
--- a/openapi/openapi.yaml
+++ b/openapi/openapi.yaml
@@ -1322,6 +1322,8 @@
'type': 'integer'
'cache_ttl_max':
'type': 'integer'
+ 'cache_optimistic':
+ 'type': 'boolean'
'upstream_mode':
'enum':
- ''