<commit_before>package WWW::Easy::AnyEventPg;
use strict;
use AnyEvent::Pg::Pool; 
use WWW::Easy::Daemon;  # for easy_try
use base 'Exporter';
# Postgres stuff for anyevent daemons
our @EXPORT = qw(db_connect db_query db_query_rows db_query_json db_query_scalar db_query_row_hashes
    db_transaction from_json to_json from_intarray to_intarray to_textarray process_json_result is_true
);

sub db_connect { 
	my ($dbhp, $connect_opts, $pool_opts) = @_;
	$pool_opts ||= {};
	$$dbhp = AnyEvent::Pg::Pool->new({
			connect_timeout => 2, 
			%$connect_opts,
		},
		size               =>10,
		connection_retries => 2,
		connection_delay   => 2,
		%$pool_opts,
		on_connect_error   => sub { 
			my ($pool, $pg) = @_; 
			warn "Connection error $connect_opts->{user}\@$connect_opts->{host}:$connect_opts->{port}/$connect_opts->{dbname}\n";
			if($pool->is_dead) { 
				warn "Pool is dead\n";
				db_connect(\$dbhp, $connect_opts, $pool_opts); # vivat the pool!
			}
   		},
	);	
}

sub db_query { 
	my ($db, $query, $cb, $err_cb) = @_;
	my $q;
#warn "WAO DB_QUERY (".(ref($query)? '['.join(', ', @$query).']' :$query).", $cb, $err_cb)\n";
	$q = $db->push_query(
		query     => $query,
		on_result => sub  {
			my $pg = shift;
			my $conn = $pg->isa('AnyEvent::Pg::Pool') ? shift : $pg;
			### почему это сделано? Если мы работаем с пулом, то параментры (pg,con,res); если с коннектом - внутри транзакции - то (pg,res);
			my $res = shift;
			my $status = $res->status;
			undef $q;

			if($status eq 'PGRES_TUPLES_OK' or $status eq 'PGRES_COMMAND_OK') {
				my $res = WWW::Easy::Daemon::easy_try { $cb->($res, $pg, $conn); } ;
				if(my $err = $@) { 
					if(ref($err)) {
						warn "Callback ERROR: ".Data::Dumper::Dumper($err); 
						return $err_cb->($err); 
					} else {
						warn "Callback ERROR: '$err'\n";
						return $err_cb->('Internal error');
					}
				}		
				return $@ ? $err_cb->($@) : $res;
			} else { 
				warn "RES STATUS=".$res->status." in ".(ref($query) eq 'ARRAY' ? join(', ', @$query) : $query )."\n";
				my $errmsg = $res->errorMessage;
				warn "ERROR '$errmsg' cb=$err_cb\n";
				my $user_error = 'Internal error';
				if($errmsg =~ /^ERROR:\s+(?:ORM:)?\s*(.*)$/s) {
					my $err = $1;
					if($err =~ /^\{/) { # если начинается на { - это JSON
						$user_error = (WWW::Easy::Daemon::easy_try { _extract_json_prefix($err) } ) || 'Incorrect JSON error message';
					}
				} elsif ($errmsg =~ /^ERROR:\s+update or delete on table "([^"]+)" violates foreign key constraint "([^"]+)" on table "([^"]+)"/) { 
					$user_error = { error => 'integrity', table => $3 };
				}
				return $err_cb->($user_error);
			}
		},
		on_error => sub { 
			warn "Error in db_query ".Data::Printer::np(@_);
			return $err_cb->('Database connection pool error');
        } 
	);
	return $q;
}

sub db_query_rows { 
	my ($db, $query, $cb, $err_cb) = @_;
	return db_query($db, $query, sub { $cb->([shift->rows]) }, $err_cb);
}<commit_msg>Пробрасывание ошибки из БД на фронтенд<commit_after>package WWW::Easy::AnyEventPg;
use strict;
use AnyEvent::Pg::Pool; 
use WWW::Easy::Daemon;  # for easy_try
use base 'Exporter';
# Postgres stuff for anyevent daemons
our @EXPORT = qw(db_connect db_query db_query_rows db_query_json db_query_scalar db_query_row_hashes
    db_transaction from_json to_json from_intarray to_intarray to_textarray process_json_result is_true
);

sub db_connect { 
	my ($dbhp, $connect_opts, $pool_opts) = @_;
	$pool_opts ||= {};
	$$dbhp = AnyEvent::Pg::Pool->new({
			connect_timeout => 2, 
			%$connect_opts,
		},
		size               =>10,
		connection_retries => 2,
		connection_delay   => 2,
		%$pool_opts,
		on_connect_error   => sub { 
			my ($pool, $pg) = @_; 
			warn "Connection error $connect_opts->{user}\@$connect_opts->{host}:$connect_opts->{port}/$connect_opts->{dbname}\n";
			if($pool->is_dead) { 
				warn "Pool is dead\n";
				db_connect(\$dbhp, $connect_opts, $pool_opts); # vivat the pool!
			}
   		},
	);	
}

sub db_query { 
	my ($db, $query, $cb, $err_cb) = @_;
	my $q;
#warn "WAO DB_QUERY (".(ref($query)? '['.join(', ', @$query).']' :$query).", $cb, $err_cb)\n";
	$q = $db->push_query(
		query     => $query,
		on_result => sub  {
			my $pg = shift;
			my $conn = $pg->isa('AnyEvent::Pg::Pool') ? shift : $pg;
			### почему это сделано? Если мы работаем с пулом, то параментры (pg,con,res); если с коннектом - внутри транзакции - то (pg,res);
			my $res = shift;
			my $status = $res->status;
			undef $q;

			if($status eq 'PGRES_TUPLES_OK' or $status eq 'PGRES_COMMAND_OK') {
				my $res = WWW::Easy::Daemon::easy_try { $cb->($res, $pg, $conn); } ;
				if(my $err = $@) { 
					if(ref($err)) {
						warn "Callback ERROR: ".Data::Dumper::Dumper($err); 
						return $err_cb->($err); 
					} else {
						warn "Callback ERROR: '$err'\n";
						return $err_cb->('Internal error');
					}
				}		
				return $@ ? $err_cb->($@) : $res;
			} else { 
				warn "RES STATUS=".$res->status." in ".(ref($query) eq 'ARRAY' ? join(', ', @$query) : $query )."\n";
				my $errmsg = $res->errorMessage;
				warn "ERROR '$errmsg' cb=$err_cb\n";
				my $user_error = 'Internal error';
				if($errmsg =~ /^ERROR:\s+(?:ORM:)?\s*(.*)$/s) {
					my $err = $1;
					if($err =~ /^\{/) { # если начинается на { - это JSON
						$user_error = (WWW::Easy::Daemon::easy_try { _extract_json_prefix($err) } ) || 'Incorrect JSON error message';
                    } elsif($err =~ /^(.*)\sat \/usr\/local/) {
                        $user_error = $1;
					}
				} elsif ($errmsg =~ /^ERROR:\s+update or delete on table "([^"]+)" violates foreign key constraint "([^"]+)" on table "([^"]+)"/) { 
					$user_error = { error => 'integrity', table => $3 };
				}
				return $err_cb->($user_error);
			}
		},
		on_error => sub { 
			warn "Error in db_query ".Data::Printer::np(@_);
			return $err_cb->('Database connection pool error');
        } 
	);
	return $q;
}

sub db_query_rows { 
	my ($db, $query, $cb, $err_cb) = @_;
	return db_query($db, $query, sub { $cb->([shift->rows]) }, $err_cb);
}
{'fraction_non_alphanumeric': 0.2035280412714262, 'fraction_numerical': 0.0024962556165751375, 'mean_word_length': 3.2533616418966735, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 61, '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': '1330096', 'n_tokens_mistral': 2669, 'n_tokens_neox': 2375, 'n_words': 514}