» /rd/lib.framework/Api/RadarisGo/NameServer.php

<?php

/**
 *
 * Minor extension to base Api_RadarisGo
 *
 * Use specific server for $api->fl_pop and $api->name_pop queries
 * This queries requires a lot of memory (huge file loaded on-demand)
 *
 * Query Removals: return REMOVED items only
 *    php> i('go-api.name-server')->removals([1147056740357836278, 165050511284695997, 16505051128469])
 *        Array(
 *       1147056740357836278 => 1
 *       165050511284695997 => $REASON
 *       )
 *
 * FULL RELOAD
 *   php> i('go-api.name-server')->removalsReload(1)
 *     Array( 0 => OK )
 *     Time: 12,277ms  << SLOW
 *
 * LOAD NEW RECORDS ONLY - (FAST)
 *   php> i('go-api.name-server')->removalsReload(0)
 *     Array( 0 => OK )
 *
 */

class Api_RadarisGo_NameServer extends Api_RadarisGo {
    static 
$MAX_ARRAY_ELEMENTS_PER_REQUEST 2000;

    
/**
     * Check is linking DIS-allowed
     * replacement for get_rd_no_links method, same return value
     * php> x i('go-api.name-server', ['socket' => 'localhost:6060'])->fl2mantra([8023690398771773, 407948878760807, 10039069442575594])
     *   8023690398771773=1
     *   10039069442575594=20
     * @return [FL => 1(blocked) | 20(non-mantra)] where linking DIS-allowed
     */
    
function fl2mantra(array $fls) { #
        
$fls array_values($fls);
        
$z $this->__xCall("fl2mantra"$fls); // list of answers
        
$r = [];
        foreach (
$z as $k => $v) {
            if (
$v && ($fls[$k]??0))
                
$r[$fls[$k]] = $v;
        }
        return 
$r;
    }

    
/**
     * Check if FL is BLOCKED
     * php> x i('go-api.name-server', ['socket' => 'localhost:6060'])->fl2blocked([8023690398771773, 407948878760807, 10039069442575594])
     *   8023690398771773=1
     * @return [FL => 1] where FL blocked
     */
    
function fl2blocked(array $fls) { #
        
$fls array_values($fls);
        
$z $this->__xCall("fl2mantra"$fls); // list of answers
        
$r = [];
        foreach (
$z as $k => $v) {
            if (
$v == 1)
                
$r[$fls[$k]] = $v;
        }
        return 
$r;
    }

    
/**
     * Wrapper around removals() API call. Allows to process huge amount of hashes in one call.
     * @param array $hashes
     * @return array
     */
    
function get_removals(array $hashes): array
    {

        if (static::
$MAX_ARRAY_ELEMENTS_PER_REQUEST < ($array_cnt count($hashes))) {
            
// Array is too large. Do multiple requests to service.
            
$position 0;
            
$res[0] = [];
            while (
$position $array_cnt) {
                
$sub_hashes array_slice($hashes$position, static::$MAX_ARRAY_ELEMENTS_PER_REQUESTtrue);
                
$sub_res $this->removals($sub_hashes);
                if (!empty(
$sub_res[0])) {
                    
$res[0] = $sub_res[0] + $res[0];
                }
                
$position $position + static::$MAX_ARRAY_ELEMENTS_PER_REQUEST;
            }
        } else {

            $res $this->removals($hashes);

        }

        return 
$res[0] ?? [];
     }

    
// FL popularity
    
function fl_pop(...$args) {
        return 
$this->_fl_server_call("fl_pop"$args);
    }

    
// Name popularity
    
function name_pop(...$args) {
        return 
$this->_fl_server_call("name_pop"$args);
    }

    function 
fname_comp($prefix) {
        return 
$this->_name_comp($prefix"first");
    }

    function 
lname_comp($prefix) {
        return 
$this->_name_comp($prefix"last");
    }

    
/**
     * FL to { Blocked, T, C, B, G, V }
     * @param array $fls
     * @return array
     * @example i('go-api.name-server')->fl2stats([HB::fl("Mathew Coomer")])
     */
    
function fl2stats(array $fls) {
        
$fls array_values($fls);
        
$r $this->__call("fl2stats"$fls); // bTCBGV
        
$z = [];
        
$cnt 0;
        foreach (
$fls as $k => $fl) {
            
$v $r[$k];
            if (! 
is_array($v)) {
                
\Log::alert("golang/fl2stats-error: ".$v);
            }
            if (
$v[1] == -2)
                
\Log::alert("golang/fl2stats-data-load-in-progress - wait ~  20 sec");
            
$z[$fl] = ["blocked" => $v[0], 't' => $v[1], 'c' => $v[2], 'b' => $v[3], 'g' => $v[4], 'v' => $v[5]];
        }
        return 
$z;
     }

    
/**
     * Internal - save
     * $hits = ['node.attr' => (float|int) value, ...]
     */
    
function istat_hit(array $hits) {
        if (! 
$hits)
            return;
        
$r $this->__call("istat_hit", [json_encode($hits)]);
        if (! 
$r) {
            if (
$cnt once()) {
               
\Log::warning("Go-Api IStat_Hit - socket: " $this->socket_name " down ; $cnt calls failed");
            }
            return;
        }
        
$r $r[0];
        if (
$r == "OK")
            return;
        
\Log::warning("Go-Api IStat_Hit error: $r");
    }

    
/**
     * Internal - save
     * $hits = ['node.attr' => (float|int) value, ...]
     */
    
function istat_sdata(array $data) {
        if (! 
$data)
            return;
        
$r $this->__call("istat_sdata", [json_encode($data)])[0];
        if (
$r == "OK")
            return;
        
\Log::warning("Go-Api IStat_HitSData error: $r");
    }

    
/*
       1. place prefix first if it is in result set  << implement in GO as if prefix is known word - return it
       2. fix rare duplicate data case

       $tp - first | last
     */
    
private function _name_comp($prefix$tp) {
        
$prefix trim(strtolower($prefix), " .,");
        
$PREFIX ucfirst(strtolower($prefix)); // canonical prefix
        
$len strlen($prefix);
        if (
$len >= && $len && $prefix[0] != "a" && $prefix[0] == $prefix[1])
            return [];
        
$r $len $this->socketCall($tp == 'first' "fname_comp" "lname_comp"$prefix) : [];
        if (! 
$r && $len 5)
            
$r DB::all_col("select name from hb_ref.profile_name where tp=? and name like ? order by cnt desc limit 20"$tp$PREFIX."%");

        
$r $r ?? [];

        
$r array_unique($r);  // minor bugs in teaser4_count (some fnames/lnames got stored as lnames/fnames for otherwise unresolvable names)

        // sort by length, then alphabetically
        
usort($r, function($a$b) {
            if (
$l strlen($a) <=> strlen($b)) return $l;
            return 
$a <=> $b;
        });

        
// if prefix is legal completion - place it first
        
$pos array_search($PREFIX$r);
        if (
$pos !== false and $pos != 0) {
            unset(
$r[$pos]);
            
array_unshift($r$PREFIX);
        }
        return 
array_values($r);
    }

    private function 
_fl_server_call($method$args) {
        return 
i("go-api.name-server", ["socket" => $this->C["fl-socket"]])->__call($method$args);
    }

}