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(:minio, :bucket)), aws_access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :access_key_id)), aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio, :secret_access_key)), aws_region: ENV.fetch("AWS_REGION", Rails.application.credentials.dig(:minio, :region)), force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio, :force_path_style)), endpoint: ENV.fetch("AWS_ENDPOINT", Rails.application.credentials.dig(:minio, :endpoint)), ) else SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new( ENV.fetch("AWS_DEV_BUCKET", Rails.application.credentials.dig(:minio_dev, :bucket)), aws_access_key_id: ENV.fetch("AWS_DEV_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :access_key_id)), aws_secret_access_key: ENV.fetch("AWS_DEV_SECRET_ACCESS_KEY_ID", Rails.application.credentials.dig(:minio_dev, :secret_access_key)), aws_region: ENV.fetch("AWS_DEV_REGION", Rails.application.credentials.dig(:minio_dev, :region)), force_path_style: ENV.fetch("AWS_FORCE_PATH_STYLE", Rails.application.credentials.dig(:minio_dev, :force_path_style)), endpoint: ENV.fetch("AWS_DEV_ENDPOINT", Rails.application.credentials.dig(:minio_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