<commit_before>require_relative 'template'
require_relative '../http/client'
require_dependency 'carto/named_maps/template'

module Carto
  module NamedMaps
    class Api

      include ::LoggerHelper

      HTTP_CONNECT_TIMEOUT_SECONDS = 45
      HTTP_REQUEST_TIMEOUT_SECONDS = 60
      RETRY_TIME_SECONDS = 2
      MAX_RETRY_ATTEMPTS = 3

      attr_accessor :user, :visualization

      def initialize(visualization)
        @visualization = visualization
        @user = visualization.user
        @named_map_template = Carto::NamedMaps::Template.new(visualization)
      end

      def index
        stats_aggregator.timing('carto-named-maps-api.index') do
          response = stats_aggregator.timing('call') do
            http_client.get(url, request_params)
          end

          if response.code.to_s.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          else
            log_response(response, 'index')
          end
        end
      end

      def create
        stats_aggregator.timing('carto-named-maps-api.create') do
          params = request_params
          params[:body] = @named_map_template.to_json

          response = http_client.post(url, params)

          response_code = response.code
          if response_code.to_s.match?(/^2/)
            response_body = ::JSON.parse(response.response_body).deep_symbolize_keys
            if response_body.key?(:limit_message)
              # Send message to support-internal
              ReporterMailer::named_maps_near_the_limit(response_body[:limit_message]).deliver_now
              # Delete 50 named maps
              clean_user_named_maps
            end
            response_body
          elsif response_code != 409 # Ignore when max number of templates is reached
            log_response(response, 'create')
          end
        end
      end

      def show
        stats_aggregator.timing('carto-named-maps-api.show') do
          response = stats_aggregator.timing('call') do
            url = url(template_name: @named_map_template.name)

            response = http_client.get(url, request_params)
          end

          response_code = response.code
          if response_code.to_s.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          else
            log_response(response, 'show') unless response_code == 404
          end
        end
      end

      def update(retries: 0)
        stats_aggregator.timing('carto-named-maps-api.update') do
          params = request_params
          params[:body] = @named_map_template.to_json

          response = http_client.put(url(template_name: @named_map_template.name), params)

          response_code_string = response.code.to_s
          if response_code_string.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          elsif (response_code_string.match?(/^5/) || response.code == 429) && retries < MAX_RETRY_ATTEMPTS
            sleep(RETRY_TIME_SECONDS**retries)
            update(retries: retries + 1)
          else
            log_response(response, 'update')
          end
        end
      end

      def destroy(retries: 0)
        stats_aggregator.timing('carto-named-maps-api.destroy') do
          url = url(template_name: @named_map_template.name)

          response = http_client.delete(url, request_params)

          response_code_string = response.code.to_s
          if response_code_string.match?(/^2/)
            response.response_body
          elsif (response_code_string.match?(/^5/) || response.code == 429) && retries < MAX_RETRY_ATTEMPTS
            sleep(RETRY_TIME_SECONDS**retries)
            destroy(retries: retries + 1)
          else
            log_response(response, 'destroy') unless response.code == 404
          end
        end
      end

      def clean_user_named_maps
        tables = Carto::UserTable.where(user_id: user.id, privacy: 0).limit(50).order('updated_at')
        named_maps_ids = tables.map { |t| "tpl_#{t.visualization.id.tr('-', '_')}" }

        named_maps_ids.each do |id|
          url = url(template_name: id)
          response = http_client.delete(url, request_params)
          response_code_string = response.code.to_s
          if (response_code_string.match?(/^5/) || response.code == 429)
            sleep(RETRY_TIME_SECONDS)
            http_client.delete(url, request_params)
          else
            log_response(response, 'clean_user_named_maps') unless response.code == 404
          end
        end
      end

      def upsert
        show ? update : create
      end

      private

      def stats_aggregator
        @@stats_aggregator_instance ||= CartoDB::Stats::EditorAPIs.instance
      end

      def url(template_name: '')
        username = user.username
        user_url = CartoDB.subdomainless_urls? ? "/user/#{username}" : ''
<commit_msg>Change the number of named maps deleted<commit_after>require_relative 'template'
require_relative '../http/client'
require_dependency 'carto/named_maps/template'

module Carto
  module NamedMaps
    class Api

      include ::LoggerHelper

      HTTP_CONNECT_TIMEOUT_SECONDS = 45
      HTTP_REQUEST_TIMEOUT_SECONDS = 60
      RETRY_TIME_SECONDS = 2
      MAX_RETRY_ATTEMPTS = 3

      attr_accessor :user, :visualization

      def initialize(visualization)
        @visualization = visualization
        @user = visualization.user
        @named_map_template = Carto::NamedMaps::Template.new(visualization)
      end

      def index
        stats_aggregator.timing('carto-named-maps-api.index') do
          response = stats_aggregator.timing('call') do
            http_client.get(url, request_params)
          end

          if response.code.to_s.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          else
            log_response(response, 'index')
          end
        end
      end

      def create
        stats_aggregator.timing('carto-named-maps-api.create') do
          params = request_params
          params[:body] = @named_map_template.to_json

          response = http_client.post(url, params)

          response_code = response.code
          if response_code.to_s.match?(/^2/)
            response_body = ::JSON.parse(response.response_body).deep_symbolize_keys
            if response_body.key?(:limit_message)
              # Send message to support-internal
              ReporterMailer::named_maps_near_the_limit(response_body[:limit_message]).deliver_now
              # Delete 100 named maps
              clean_user_named_maps
            end
            response_body
          elsif response_code != 409 # Ignore when max number of templates is reached
            log_response(response, 'create')
          end
        end
      end

      def show
        stats_aggregator.timing('carto-named-maps-api.show') do
          response = stats_aggregator.timing('call') do
            url = url(template_name: @named_map_template.name)

            response = http_client.get(url, request_params)
          end

          response_code = response.code
          if response_code.to_s.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          else
            log_response(response, 'show') unless response_code == 404
          end
        end
      end

      def update(retries: 0)
        stats_aggregator.timing('carto-named-maps-api.update') do
          params = request_params
          params[:body] = @named_map_template.to_json

          response = http_client.put(url(template_name: @named_map_template.name), params)

          response_code_string = response.code.to_s
          if response_code_string.match?(/^2/)
            ::JSON.parse(response.response_body).deep_symbolize_keys
          elsif (response_code_string.match?(/^5/) || response.code == 429) && retries < MAX_RETRY_ATTEMPTS
            sleep(RETRY_TIME_SECONDS**retries)
            update(retries: retries + 1)
          else
            log_response(response, 'update')
          end
        end
      end

      def destroy(retries: 0)
        stats_aggregator.timing('carto-named-maps-api.destroy') do
          url = url(template_name: @named_map_template.name)

          response = http_client.delete(url, request_params)

          response_code_string = response.code.to_s
          if response_code_string.match?(/^2/)
            response.response_body
          elsif (response_code_string.match?(/^5/) || response.code == 429) && retries < MAX_RETRY_ATTEMPTS
            sleep(RETRY_TIME_SECONDS**retries)
            destroy(retries: retries + 1)
          else
            log_response(response, 'destroy') unless response.code == 404
          end
        end
      end

      def clean_user_named_maps
        tables = Carto::UserTable.where(user_id: user.id, privacy: 0).limit(100).order('updated_at')
        named_maps_ids = tables.map { |t| "tpl_#{t.visualization.id.tr('-', '_')}" }

        named_maps_ids.each do |id|
          url = url(template_name: id)
          response = http_client.delete(url, request_params)
          response_code_string = response.code.to_s
          if (response_code_string.match?(/^5/) || response.code == 429)
            sleep(RETRY_TIME_SECONDS)
            http_client.delete(url, request_params)
          else
            log_response(response, 'clean_user_named_maps') unless response.code == 404
          end
        end
      end

      def upsert
        show ? update : create
      end

      private

      def stats_aggregator
        @@stats_aggregator_instance ||= CartoDB::Stats::EditorAPIs.instance
      end

      def url(template_name: '')
        username = user.username
        user_url = CartoDB.subdomainless_urls? ? "/user/#{username}" : ''

{'fraction_non_alphanumeric': 0.0923202614379085, 'fraction_numerical': 0.009191176470588236, 'mean_word_length': 2.2352163858605882, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2615859', 'n_tokens_mistral': 2957, 'n_tokens_neox': 2814, 'n_words': 514}