- Update AWS S3 adapter configuration to set the access control list (ACL) to private for both production and development environments. - This ensures that the sitemap files are not publicly accessible and are only retrievable by authorized users or applications, improving security.
132 lines
5.0 KiB
Ruby
132 lines
5.0 KiB
Ruby
class RefreshSitemapWorker
|
|
include Sidekiq::Worker
|
|
require "redis"
|
|
|
|
def perform
|
|
lock_key = "refresh_sitemap_lock"
|
|
lock_ttl = 60 # 锁的生存时间,单位为秒
|
|
|
|
redis = Redis.new(url: ENV.fetch("REDIS_URL", "redis://localhost:6379/1"))
|
|
|
|
if redis.set(lock_key, Time.current.to_s, nx: true, ex: lock_ttl)
|
|
begin
|
|
setup_sitemap_config
|
|
# 生成默认的不带语言前缀的 sitemap
|
|
generate_sitemap(nil)
|
|
|
|
# 为每个可用语言生成带前缀的 sitemap
|
|
I18n.available_locales.each do |locale|
|
|
generate_sitemap(locale)
|
|
end
|
|
ensure
|
|
redis.del(lock_key)
|
|
end
|
|
else
|
|
Rails.logger.info "Sitemap refresh is already in progress"
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def setup_sitemap_config
|
|
@host = Rails.env.production? ? "https://todayaiweather.com" : "http://127.0.0.1:3000"
|
|
Rails.application.routes.default_url_options[:host] = @host
|
|
SitemapGenerator::Sitemap.default_host = ENV.fetch("RAILS_SITEMAP_DEFAULT_HOST", @host)
|
|
|
|
if Rails.env.production?
|
|
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
|
ENV.fetch("AWS_BUCKET", Rails.application.credentials.dig(:s3, :bucket)),
|
|
acl: "private",
|
|
aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:s3, :access_key_id)),
|
|
aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:s3, :secret_access_key)),
|
|
aws_region: ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:s3, :region)),
|
|
force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:s3, :force_path_style)),
|
|
endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:s3, :endpoint)),
|
|
)
|
|
else
|
|
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
|
|
ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:s3_dev, :bucket)),
|
|
acl: "private",
|
|
aws_access_key_id: ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:s3_dev, :access_key_id)),
|
|
aws_secret_access_key: ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:s3_dev, :secret_access_key)),
|
|
aws_region: ENV.fetch("AWS_DEV_REGION", Rails.application.credentials.dig(:s3_dev, :region)),
|
|
force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:s3_dev, :force_path_style)),
|
|
endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:s3_dev, :endpoint)),
|
|
)
|
|
end
|
|
SitemapGenerator::Sitemap.sitemaps_path = "sitemaps/"
|
|
end
|
|
|
|
def generate_sitemap(locale = nil)
|
|
# 设置当前语言环境
|
|
I18n.locale = locale || I18n.default_locale
|
|
Rails.application.routes.default_url_options[:locale] = locale
|
|
|
|
# 设置 sitemap 路径
|
|
# path_prefix = locale ? "sitemaps/#{locale}/" : "sitemaps/"
|
|
# SitemapGenerator::Sitemap.sitemaps_path = path_prefix
|
|
|
|
filename = locale==nil ? "sitemap" : "sitemap_#{locale}"
|
|
SitemapGenerator::Sitemap.create(filename: filename) do
|
|
available_locales = I18n.available_locales
|
|
|
|
# 首页
|
|
add root_path(locale: locale),
|
|
changefreq: "daily",
|
|
priority: 1.0,
|
|
alternate: available_locales.map { |al|
|
|
{ lang: al, href: root_url(locale: al) }
|
|
}
|
|
|
|
# 城市列表页
|
|
add cities_path(locale: locale),
|
|
changefreq: "daily",
|
|
priority: 0.9,
|
|
alternate: available_locales.map { |al|
|
|
{ lang: al, href: cities_url(locale: al) }
|
|
}
|
|
|
|
# 艺术作品列表页
|
|
add arts_path(locale: locale),
|
|
changefreq: "daily",
|
|
priority: 0.9,
|
|
alternate: available_locales.map { |al|
|
|
{ lang: al, href: arts_url(locale: al) }
|
|
}
|
|
|
|
# 城市详情页
|
|
City.find_each do |city|
|
|
add city_path(city, locale: locale),
|
|
changefreq: "daily",
|
|
priority: 0.8,
|
|
lastmod: city.updated_at,
|
|
alternate: available_locales.map { |al|
|
|
{ lang: al, href: city_url(city, locale: al) }
|
|
}
|
|
end
|
|
|
|
# 天气艺术作品页
|
|
WeatherArt.includes(:city).find_each do |art|
|
|
if art.image.attached?
|
|
add city_weather_art_path(art.city, art, locale: locale),
|
|
changefreq: "daily",
|
|
priority: 0.7,
|
|
lastmod: art.updated_at,
|
|
images: [ {
|
|
loc: url_for(art.image),
|
|
title: "#{art.city.name} Weather Art - #{art.weather_date.strftime('%B %d, %Y')}"
|
|
} ],
|
|
alternate: available_locales.map { |al|
|
|
{ lang: al, href: city_weather_art_url(art.city, art, locale: al) }
|
|
}
|
|
end
|
|
end
|
|
end
|
|
|
|
Rails.logger.info "Generated sitemap for #{locale || 'default'} version"
|
|
rescue => e
|
|
Rails.logger.error "Error generating sitemap for #{locale || 'default'}: #{e.message}"
|
|
raise e
|
|
end
|
|
end
|