228 lines
11 KiB
Ruby
228 lines
11 KiB
Ruby
|
require 'date'
|
||
|
require_relative '../../app/services/carto/data_library_service'
|
||
|
require_relative '../../lib/carto_api/json_client'
|
||
|
|
||
|
namespace :cartodb do
|
||
|
|
||
|
namespace :remotes do
|
||
|
|
||
|
task :clear, [:username] => [:environment] do |t, args|
|
||
|
username = args[:username]
|
||
|
raise 'username required' unless username.present?
|
||
|
|
||
|
u = ::User.where(username: username).first
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
deleted = CartoDB::Visualization::CommonDataService.new.delete_common_data_for_user(u)
|
||
|
puts "Deleted #{deleted} remote visualizations"
|
||
|
end
|
||
|
|
||
|
task :clear_org, [:org_name] => [:environment] do |t, args|
|
||
|
org_name = args[:org_name]
|
||
|
raise 'organization name required' unless org_name.present?
|
||
|
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
common_data_service = CartoDB::Visualization::CommonDataService.new
|
||
|
o = Organization.where(name: org_name).first
|
||
|
o.users.each { |u|
|
||
|
common_data_service.delete_common_data_for_user(u)
|
||
|
}
|
||
|
end
|
||
|
|
||
|
desc 'Load common data account remotes. Pass username as first argument. Example: `rake cartodb:remotes:reload[development]`'
|
||
|
task :reload, [:username] => [:environment] do |t, args|
|
||
|
username = args[:username]
|
||
|
raise 'username required' unless username.present?
|
||
|
|
||
|
u = ::User.where(username: username).first
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
vis_api_url = get_visualizations_api_url
|
||
|
CartoDB::Visualization::CommonDataService.new.load_common_data_for_user(u, vis_api_url)
|
||
|
end
|
||
|
|
||
|
desc 'Load common data account remotes for a whole organization. Pass organization name as first argument. Example: `rake cartodb:remotes:reload[my_team]`'
|
||
|
task :reload_org, [:org_name] => [:environment] do |t, args|
|
||
|
org_name = args[:org_name]
|
||
|
raise 'organization name required' unless org_name.present?
|
||
|
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
common_data_service = CartoDB::Visualization::CommonDataService.new
|
||
|
vis_api_url = get_visualizations_api_url
|
||
|
o = Organization.where(name: org_name).first
|
||
|
o.users.each {|u|
|
||
|
common_data_service.load_common_data_for_user(u, vis_api_url)
|
||
|
}
|
||
|
end
|
||
|
|
||
|
desc 'Load common data account remotes for multiple users, in alphabetical order. If you pass a username, it will do it beginning in the next username'
|
||
|
task :load_all, [:from_username] => [:environment] do |t, args|
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
common_data_service = CartoDB::Visualization::CommonDataService.new
|
||
|
vis_api_url = get_visualizations_api_url
|
||
|
puts DateTime.now
|
||
|
# TODO: batch
|
||
|
users = ::User.order_by(:username)
|
||
|
users = users.where("username > '#{args[:from_username]}'") unless args[:from_username].nil?
|
||
|
users.all.each do |user|
|
||
|
added, updated, not_modified, removed, failed = common_data_service.load_common_data_for_user(user, vis_api_url)
|
||
|
printf("%20s: +%03d; *%03d; =%03d; -%03d; e%03d\n", user.username, added, updated, not_modified, removed, failed)
|
||
|
end
|
||
|
puts DateTime.now
|
||
|
end
|
||
|
|
||
|
load_in_data_library_mandatory_args = [:scheme, :base_domain, :port, :source_username,
|
||
|
:source_api_key, :target_username, :granted_api_key]
|
||
|
load_in_data_library_optional_args = [:format]
|
||
|
load_in_data_library_from_api_key_args = load_in_data_library_mandatory_args + load_in_data_library_optional_args
|
||
|
# Example: rake cartodb:remotes:load_in_data_library_from_api_key[https,carto.com,80,s_user,s_user_key,t_user,g_key,[format]]
|
||
|
desc 'Loads all datasets for a API key in a Data Library. `granted_api_key` will be stored for importing.'
|
||
|
task :load_in_data_library_from_api_key, load_in_data_library_from_api_key_args => [:environment] do |_, args|
|
||
|
raise "All arguments are mandatory" unless load_in_data_library_mandatory_args.all? { |a| args[a].present? }
|
||
|
format_arg = args[:format] || 'gpkg'
|
||
|
|
||
|
client = CartoAPI::JsonClient.new(
|
||
|
scheme: args['scheme'], base_domain: args['base_domain'], port: args['port'].to_i
|
||
|
)
|
||
|
service = Carto::DataLibraryService.new
|
||
|
service.load_datasets!(client,
|
||
|
source_username: args['source_username'], source_api_key: args['source_api_key'],
|
||
|
target_username: args['target_username'], granted_api_key: args['granted_api_key'],
|
||
|
format: format_arg)
|
||
|
end
|
||
|
|
||
|
load_in_data_library_mandatory_with_source_args = load_in_data_library_mandatory_args + ['source_dataset']
|
||
|
load_in_data_library_args = load_in_data_library_mandatory_with_source_args + load_in_data_library_optional_args
|
||
|
# Example: rake cartodb:remotes:load_in_data_library[https,carto.com,80,s_data,s_user,s_user_key,t_user,g_key, source_dataset, [format]]
|
||
|
desc 'Loads a dataset in a Data Library. `granted_api_key` is the key that will be stored for importing.'
|
||
|
task :load_in_data_library, load_in_data_library_args => [:environment] do |_, args|
|
||
|
raise "All arguments except format are mandatory" unless load_in_data_library_mandatory_with_source_args.all? { |a| args[a].present? }
|
||
|
format_arg = args[:format] || 'gpkg'
|
||
|
|
||
|
client = CartoAPI::JsonClient.new(
|
||
|
scheme: args['scheme'], base_domain: args['base_domain'], port: args['port'].to_i
|
||
|
)
|
||
|
service = Carto::DataLibraryService.new
|
||
|
service.load_dataset!(client,
|
||
|
source_dataset: args['source_dataset'], source_username: args['source_username'],
|
||
|
source_api_key: args['source_api_key'],
|
||
|
target_username: args['target_username'], granted_api_key: args['granted_api_key'],
|
||
|
format: format_arg)
|
||
|
end
|
||
|
|
||
|
desc 'Removes a Data Library entry from a user'
|
||
|
task :remove_from_data_library, [:username, :visualization_name] => [:environment] do |_, args|
|
||
|
username = args['username']
|
||
|
name = args['visualization_name']
|
||
|
raise 'All Arguments except format are mandatory' unless username.present? && name.present?
|
||
|
|
||
|
user = Carto::User.find_by_username(username)
|
||
|
raise 'User not found' unless user
|
||
|
|
||
|
visualization = user.visualizations.remotes.find_by_name(name)
|
||
|
raise 'Visualization not found' unless visualization
|
||
|
|
||
|
visualization.destroy
|
||
|
end
|
||
|
|
||
|
desc "Invalidate user's date flag and make them refresh data library"
|
||
|
task :invalidate_common_data => [:environment] do
|
||
|
require_relative '../../app/helpers/common_data_redis_cache'
|
||
|
require_relative '../../app/services/visualization/common_data_service'
|
||
|
|
||
|
invalidate_sql = %Q[
|
||
|
UPDATE users
|
||
|
SET last_common_data_update_date = null
|
||
|
WHERE last_common_data_update_date >= now() - '#{::User::COMMON_DATA_ACTIVE_DAYS} day'::interval;
|
||
|
]
|
||
|
updated_rows = SequelRails.connection.fetch(invalidate_sql).update
|
||
|
CommonDataRedisCache.new.invalidate
|
||
|
puts "#{updated_rows} users invalidated"
|
||
|
|
||
|
# Now we try to add the new common-data request to the cache using the common_data user
|
||
|
common_data_user = ::User.where(username: Cartodb.get_config(:common_data, 'username')).first
|
||
|
if !common_data_user.nil?
|
||
|
vis_api_url = get_visualizations_api_url
|
||
|
CartoDB::Visualization::CommonDataService.new.load_common_data_for_user(common_data_user, vis_api_url)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def get_visualizations_api_url
|
||
|
common_data_config = Cartodb.config[:common_data]
|
||
|
username = common_data_config["username"]
|
||
|
base_url = common_data_config["base_url"].nil? ? CartoDB.base_url(username) : common_data_config["base_url"]
|
||
|
base_url + "/api/v1/viz?type=table&privacy=public"
|
||
|
end
|
||
|
|
||
|
module RemoteTablesMaintenanceRake
|
||
|
def self.delete_remote_visualizations(user)
|
||
|
user.update_column(:last_common_data_update_date, nil)
|
||
|
|
||
|
user.visualizations.where(type: 'remote').each do |v|
|
||
|
begin
|
||
|
unless v.external_source
|
||
|
puts " Remote visualization #{v.id} does not have a external source. Skipping..."
|
||
|
next
|
||
|
end
|
||
|
if v.external_source.external_data_imports.any?
|
||
|
puts " Remote visualization #{v.id} has been previously imported. Skipping..."
|
||
|
next
|
||
|
end
|
||
|
|
||
|
v.external_source.delete
|
||
|
v.delete
|
||
|
rescue StandardError => e
|
||
|
puts " Error deleting visualization #{v.id}: #{e.message}"
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Removes common data visualizations from users which have not seen activity in some time
|
||
|
# e.g: rake cartodb:remotes:remove_from_inactive_users[365,90] will affect all users
|
||
|
# whose last activity was between 1 year and 3 months ago
|
||
|
desc 'Remove common data visualizations from inactive users'
|
||
|
task :remove_from_inactive_users, [:start_days_ago, :end_days_ago] => :environment do |_t, args|
|
||
|
start_days_ago = args[:start_days_ago].try(:to_i) || 365 * 2
|
||
|
end_days_ago = args[:end_days_ago].try(:to_i) || 30 * 3
|
||
|
raise 'Invalid date interval' unless start_days_ago > end_days_ago && end_days_ago > 0
|
||
|
start_date = DateTime.now - start_days_ago
|
||
|
end_date = DateTime.now - end_days_ago
|
||
|
|
||
|
puts "Removing common data visualizations for users with last activity between #{start_date} and #{end_date}"
|
||
|
query = Carto::User.where("COALESCE(dashboard_viewed_at, created_at) BETWEEN '#{start_date}' AND '#{end_date}'")
|
||
|
.where(account_type: 'FREE')
|
||
|
user_count = query.count
|
||
|
puts "#{user_count} users will be affected. Starting in 10 seconds unless canceled (ctrl+C)"
|
||
|
sleep 10
|
||
|
|
||
|
processed = 0
|
||
|
query.find_each do |user|
|
||
|
processed += 1
|
||
|
puts "#{user.username} (#{processed} / #{user_count})"
|
||
|
RemoteTablesMaintenanceRake.delete_remote_visualizations(user)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Removes common data visualizations from a specific user
|
||
|
desc 'Remove common data visualizations from user'
|
||
|
task :remove_from_user, [:username] => :environment do |_t, args|
|
||
|
RemoteTablesMaintenanceRake.delete_remote_visualizations(Carto::User.find_by_username(args[:username]))
|
||
|
end
|
||
|
|
||
|
# Removes common data visualizations from a specific organization
|
||
|
desc 'Remove common data visualizations from user'
|
||
|
task :remove_from_organization, [:orgname] => :environment do |_t, args|
|
||
|
query = Carto::User.where(organization_id: Carto::Organization.find_by_name(args[:orgname]).id)
|
||
|
user_count = query.count
|
||
|
puts "#{user_count} users will be affected."
|
||
|
|
||
|
processed = 0
|
||
|
query.find_each do |user|
|
||
|
processed += 1
|
||
|
puts "#{user.username} (#{processed} / #{user_count})"
|
||
|
RemoteTablesMaintenanceRake.delete_remote_visualizations(user)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|