阻止缓存阻止请求并自动重新生成新缓存
我们可以轻松制作Rails cache
,并设置过期时间
Rails.cache.fetch(cache_key, expires_in: 1.minute) do
`fetch_data_from_mongoDB_with_complex_query`
end
不知何故,当新请求进入时,会发生过期,请求将被阻止。我的问题是,我怎样才能避免这种情况?基本上,我希望在Rails进行缓存时将先前的缓存提供给客户端的请求。
如预期的行为图所示,第二个请求将获得cache 1
但不会获得cache 2
,尽管Rails正在为cache 2
做出贡献。因此,用户不必花费太多时间来制作新的缓存。那么,如何在没有用户的情况下自动重新生成所有缓存。请求触发它?
cache_key = "#{__callee__}"
Rails.cache.fetch(cache_key, expires_in: 1.hour) do
all.order_by(updated_at: -1).limit(max_rtn_count)
end
如何在命令中获取所有缓存的密钥?
因为缓存的查询可以通过start_date
,end_date
,depature_at
,arrive_at
的组合生成。
无法手动使所有缓存密钥无效。
如何获取所有缓存键,然后在Rake任务中刷新
答案 0 :(得分:3)
使用expiration
非常棘手,因为一旦缓存的对象过期,您将无法获取过期的值。
最佳做法是将缓存刷新过程与最终用户流量分离。您需要一个rake任务来填充/刷新缓存并将该任务作为cron运行。如果由于某种原因,作业未运行,缓存将过期,您的用户将需要额外的时间来获取数据。
但是,如果您的数据集太大而无法一次刷新/加载所有数据集,则必须使用不同的缓存过期策略(您可以在每次缓存命中后更新到期时间)。
或者,您可以禁用缓存过期并使用其他指示符(例如时间)来确定缓存中的对象是最新还是失效。如果它是陈旧的,您可以使用异步ActiveJob
工作程序对作业进行排队以更新缓存。过时的数据将返回给用户,缓存将在后台更新。
答案 1 :(得分:2)
It seems to be working how caching is designed to work. When the second request comes in, after // Get the dependencies that have already been installed
// to ./node_modules with `npm install <dep>`in the root director
// of your app
var _ = require('underscore'),
PDFParser = require('pdf2json');
var pdfParser = new PDFParser();
// Create a function to handle the pdf once it has been parsed.
// In this case we cycle through all the pages and extraxt
// All the text blocks and print them to console.
// If you do `console.log(JSON.stringify(pdf))` you will
// see how the parsed pdf is composed. Drill down into it
// to find the data you are looking for.
var _onPDFBinDataReady = function (pdf) {
console.log('Loaded pdf:\n');
for (var i in pdf.data.Pages) {
var page = pdf.data.Pages[i];
for (var j in page.Texts) {
var text = page.Texts[j];
console.log(text.R[0].T);
}
}
};
// Create an error handling function
var _onPDFBinDataError = function (error) {
console.log(error);
};
// Use underscore to bind the data ready function to the pdfParser
// so that when the data ready event is emitted your function will
// be called. As opposed to the example, I have used `this` instead
// of `self` since self had no meaning in this context
pdfParser.on('pdfParser_dataReady', _.bind(_onPDFBinDataReady, this));
// Register error handling function
pdfParser.on('pdfParser_dataError', _.bind(_onPDFBinDataError, this));
// Construct the file path of the pdf
var pdfFilePath = 'test3.pdf';
// Load the pdf. When it is loaded your data ready function will be called.
pdfParser.loadPDF(pdfFilePath);
in your case, the query re-runs and blocks the request while the query is running.
What you want is for Rails to return a 1hr
the original expired cached while its working on generating the new cache1
.
But think about what you are asking? You are asking it to return something which has expired? How could rails return cache2
, when it has expired. This happened because you explicitly set the cache to expire in exactly 1 hour.
There could be many ways to achieve what you want, here is one solution which comes immediately to mind: