UNPKG

@joergmittaglawo/dmvconfig

Version:

DMV Configuration scripts for Lawo V__matrix Distributed Multiviewers.

1 lines 32 kB
Object.defineProperty(exports,"__esModule",{value:!0}),exports.RuntimeConstants=exports.ModuleRegistry=exports.ComponentState=exports.NamedTableRow=exports.TableRow=exports.NamedTable=exports.Table=exports.Root=exports.Subtree=exports.VSocket=exports.EventHandler=exports.ThumbnailListener=exports.GlobalListener=exports.Listener=void 0;const e=require("./schema_annotated"),t=require("./node_http"),s=require("./node_util"),n=require("./node_ws"),i=require("./utilities"),r=require("./resource_cache"),o=require("./vmodel");class a{constructor(e,t,s,n,i){this.listener_type=e,this.kwl=t,this.kw=s,this.id=n,this.destructor=i}unregister(){this.destructor()}}exports.Listener=a;class l{constructor(e,t){this.id=e,this.destructor=t}unregister(){this.destructor()}}exports.GlobalListener=l;class c{constructor(e,t){this.id=e,this.destructor=t}unregister(){this.destructor()}}exports.ThumbnailListener=c;class h{constructor(e,t,s){this.handler_type=e,this.id=t,this.destructor=s}unregister(){this.destructor()}}exports.EventHandler=h;class _{constructor(){this.partial_kwls=Object.create(null)}push(e){Object.prototype.hasOwnProperty.call(this.partial_kwls,e.kwl)||(this.partial_kwls[e.kwl]=Object.create(null)),this.partial_kwls[e.kwl][e.kw]=e.cache}flush(e){let t=0;for(const s in this.partial_kwls)++t<50&&(e({kwl:s,kws:this.partial_kwls[s]}),delete this.partial_kwls[s])}}function u(e){const t=e.indexOf(".");return-1!==t?e.substring(0,t):e}class d{constructor(e){var t,s,r,o,a;this.m_table_requests={next_table_request_id:0},this.state={type:"disconnected"},this.subscription_interval=null,this.lazy_handler_interval=null,this.reconnect_interval=null,this.connect_timer=null,this.id_pool=new i.IDPool,this.m_expected_message_type=0,this.check_towel_on_write=!0,this.check_component_liveness=!0,this.listeners=Object.create(null),this.globalListeners=[],this.pending_markers=new Map,this.pending_lazy_kw_updates=Object.create(null),this.pending_subscriptions=new _,this.open_handlers=new Map,this.error_handlers=new Map,this.close_handlers=new Map,this.thumbnails=null,this.reconnect_automatically=!1,this.is_online=!1,this.subscription_interval=setInterval(()=>{this.execute_pending_subscription_requests()},50),this.lazy_handler_interval=setInterval(()=>{this.execute_lazy_handlers()},100);const l=null!==(t=e.protocol)&&void 0!==t?t:"ws";this.connection_pars={...e,protocol:l,port:null!==(s=e.port)&&void 0!==s?s:"ws"===l?80:443,cache_everything:null!==(r=e.cache_everything)&&void 0!==r&&r,reject_unauthorized:null===(o=e.reject_unauthorized)||void 0===o||o,timeout_ms:d.scaledTimeout(e.timeout_ms),max_payload_size:null!==(a=e.max_payload_size)&&void 0!==a?a:1048576},this.web_socket=new n.Adapter(this.connection_pars)}static scaledTimeout(e){return(null!=e?e:5e3)*d.s_timeout_scale}static setTimeoutScale(e){this.s_timeout_scale=e}is_ready(){return"ready"===this.state.type}get protocol_features(){switch(this.state.type){case"disconnected":return{create_row_request_id:!1};default:return this.state.protocol_features}}set_snooper(e){void 0!==e.inbound&&(this.snoop_inbound_handler=e.inbound),void 0!==e.outbound&&(this.snoop_outbound_handler=e.outbound)}get current_towel(){return s.assert(this.m_current_towel),this.m_current_towel}get build_info(){return this.state.build_info}get ip(){return this.connection_pars.ip}get protocol(){return this.connection_pars.protocol}get port(){return this.connection_pars.port}get towel(){return this.connection_pars.towel}get runtime_constants(){return this.state.runtime_constants}get schema(){return this.state.annotated_schema}get module_registry(){return this.state.module_registry}get root(){return new k(this,this.m_table_requests)}async place_towel(){s.assert(this.current_towel),s.assert(0!==this.current_towel.state),this.m_current_towel={value:this.towel,state:1},this.root.write({kwl:"system.usrinfo",kw:"towel"},this.towel,{check_towel:!1})}async marker(e){var t,n;const i=(new Date).valueOf()+1e3*(null!==(t=null==e?void 0:e.timeout)&&void 0!==t?t:5),r=null!==(n=null==e?void 0:e.id)&&void 0!==n?n:(()=>{for(let e=0;e<32768;++e)if(!this.pending_markers.has(e))return e;return s.assert(!1),-1})();if(r>=0)return new Promise((e,t)=>{this.pending_markers.set(r,{expiryDateMS:i,resolve:e,reject:t}),this.send([{op:"marker",marker:32768|r}])});s.assert(!1)}query_cache(e,t){if(Object.prototype.hasOwnProperty.call(this.listeners,e)&&Object.prototype.hasOwnProperty.call(this.listeners[e],t))return this.listeners[e][t].cached_value}find_runtime_constant(e){const t=e.split("::");if(2!==t.length)throw new Error(`Invalid constant specifier '${e}'. Valid specifiers read as follows: SomeComponent::some_constant_name`);return this.runtime_constants.find_constant(this.module_registry.translate_component_ua_name(t[0]),t[1])}get_runtime_constant(e){const t=this.find_runtime_constant(e);if(void 0===t)throw new Error(`Unknown runtime constant '${e}'`);return t}send(e){var t;this.web_socket.send(JSON.stringify(e)),null===(t=this.snoop_outbound_handler)||void 0===t||t.call(this,e)}on_open(e,t){const s=this.get_id(this.open_handlers,t);return this.open_handlers.set(s,e),new h(0,s,()=>{this.open_handlers.delete(s)})}on_close(e,t){const s=this.get_id(this.close_handlers,t);return this.close_handlers.set(s,e),new h(1,s,()=>{this.close_handlers.delete(s)})}on_error(e,t){const s=this.get_id(this.close_handlers,t);return this.error_handlers.set(s,e),new h(2,s,()=>{this.error_handlers.delete(s)})}static async open(e){const t=d.scaledTimeout(e.timeout_ms);let s=t,n=new d(e);const i=(new Date).valueOf();let r=!1;try{const[e,o]=await n.open_ws(s);r=!0;s-=(new Date).valueOf()-i,await n.initialize(e,o,Math.max(s,500));let a=!1;n.on_close(()=>{a=!1,n.state={type:"disconnected"}},"disconnect_on_close"),n.on_open(()=>{a=!0,n.m_expected_message_type=0,n.initialize(e,o,Math.max(3e4,t)).catch(e=>{a&&n.web_socket.reopen()})},"reinit_on_open")}catch(e){throw r&&await n.close(),e}return n}arm_reconnect_timer(){if(null===this.reconnect_interval){const e=5e3;this.reconnect_interval=setInterval(()=>{try{this.web_socket.reopen()}catch(e){}},e)}}async close(){this.reconnect_automatically=!1;try{this.m_current_towel&&this.m_current_towel.value.length>0&&this.m_current_towel.value===this.connection_pars.towel&&this.root.write_unchecked({kwl:"system.usrinfo",kw:"towel"},"")}finally{this.is_online=!1;try{this.web_socket.close()}catch(e){}clearInterval(this.subscription_interval),this.subscription_interval=null,clearInterval(this.lazy_handler_interval),null!==this.reconnect_interval&&clearInterval(this.reconnect_interval),null!==this.connect_timer&&clearInterval(this.connect_timer)}}reboot(e){return this.root.reboot(e)}reset(e){return this.root.reset(e)}execute_pending_subscription_requests(){if(!this.is_online)return;this.pending_subscriptions.flush(e=>{this.send([{op:"subscribe",kwl:e.kwl,kw:Object.keys(e.kws)}]);for(const t in e.kws)Object.prototype.hasOwnProperty.call(this.listeners,e.kwl)||(this.listeners[e.kwl]=Object.create(null)),Object.prototype.hasOwnProperty.call(this.listeners[e.kwl],t)||(this.listeners[e.kwl][t]={handlers:Object.create(null)}),this.listeners[e.kwl][t].cached_value=void 0});const e=(new Date).valueOf();for(const[t,s]of this.pending_markers)e>s.expiryDateMS&&(s.reject(new Error(`Marker ${t} timed out`)),this.pending_markers.delete(t))}async recovery(e){var t;const s=d.scaledTimeout(1e3*(null!==(t=null==e?void 0:e.timeout)&&void 0!==t?t:75));for(const e=(new Date).valueOf();(new Date).valueOf()<e+s;){if(this.is_ready())return;await i.pause(4)}throw new Error(`${this.connection_pars.ip} failed to recover within ${Math.round(s/1e3)} s; maybe the machine had to swap partitions?`)}dump_listener_stats(){let e=0,t=0,s=0;for(const n in this.listeners){e+=n.length;for(const e in this.listeners[n]){t+=e.length;for(const t in this.listeners[n][e].handlers)s+=t.length}}return{kwl_bytes:e,kw_bytes:t,id_bytes:s}}get_id(e,t){return t||this.id_pool.get_id()}ensure_kw_listener(e){return Object.prototype.hasOwnProperty.call(this.listeners,e.kwl)||(this.listeners[e.kwl]=Object.create(null)),Object.prototype.hasOwnProperty.call(this.listeners[e.kwl],e.kw)||(this.listeners[e.kwl][e.kw]={handlers:{}}),e.cache&&!Object.prototype.hasOwnProperty.call(this.listeners[e.kwl][e.kw],"cached_value")&&(this.listeners[e.kwl][e.kw].cached_value=void 0),e.defer_subscription?this.pending_subscriptions.push(e):this.send([{op:"subscribe",kwl:e.kwl,kw:[e.kw]},{op:"readAll",kwl:e.kwl,kw:[e.kw]}]),this.listeners[e.kwl][e.kw]}renew_subscriptions(){for(const e in this.listeners)for(const t in this.listeners[e])this.pending_subscriptions.push({kwl:e,kw:t,cache:Object.prototype.hasOwnProperty.call(this.listeners[e][t],"cached_value")});this.execute_pending_subscription_requests()}safely_delete_handler(e){Object.prototype.hasOwnProperty.call(this.listeners,e.kwl)&&Object.prototype.hasOwnProperty.call(this.listeners[e.kwl],e.kw)&&delete this.listeners[e.kwl][e.kw].handlers[e.id]}register_kw_listener(e,t){var s,n;let i=this.ensure_kw_listener({kwl:e.kwl,kw:e.kw,cache:null!==(s=e.cache)&&void 0!==s&&s,defer_subscription:null!==(n=e.defer_subscription)&&void 0!==n&&n});const r=this.get_id(i.handlers,e.listener_id);switch(e.listener_type){case 0:i.handlers[r]={handler:t,execution_strategy:e.execution_strategy};break;case 1:i.handlers[r]={handler:s=>{t(s),this.safely_delete_handler({kwl:e.kwl,kw:e.kw,id:r})},execution_strategy:e.execution_strategy}}return new a(e.listener_type,e.kwl,e.kw,r,()=>{this.safely_delete_handler({kwl:e.kwl,kw:e.kw,id:r}),0===Object.keys(i.handlers).length&&(this.is_online&&this.send([{op:"unsubscribe",kwl:e.kwl,kw:[e.kw]}]),delete this.listeners[e.kwl][e.kw],0===Object.keys(this.listeners[e.kwl]).length&&(delete this.listeners[e.kwl],this.is_online&&this.send([{op:"unsubscribe",kwl:e.kwl}])))})}register_global_listener(e,t){var s;const n=null!==(s=t.listener_id)&&void 0!==s?s:this.id_pool.get_id();return this.globalListeners=this.globalListeners.filter(e=>e[1]!==n),this.globalListeners.push([e,n]),new l(n,()=>{this.globalListeners=this.globalListeners.filter(e=>e[1]!==n)})}register_thumbnail_listener(e,t){null===this.thumbnails&&(this.send([{op:"subscribe",kwl:"monitoring.live_view",kw:["thumbnail_header","thumbnail"]}]),this.thumbnails={header_data:void 0,prev_data:void 0,handlers:new Map}),s.assert(this.thumbnails);const n=this.get_id(this.thumbnails.handlers,null==t?void 0:t.listener_id);return this.thumbnails.handlers.set(n,e),new c(n,()=>{this.thumbnails&&(this.thumbnails.handlers.delete(n),0===this.thumbnails.handlers.size&&(this.thumbnails=null,this.send([{op:"unsubscribe",kwl:"monitoring.live_view",kw:["thumbnail_header","thumbnail"]}])))})}execute_lazy_handlers(){for(const e in this.pending_lazy_kw_updates){const t=this.pending_lazy_kw_updates[e];t.handler(t.payload)}this.pending_lazy_kw_updates={}}open_ws(e){return new Promise((t,s)=>{let n=null;try{this.connect_timer&&clearTimeout(this.connect_timer),this.connect_timer=setTimeout(()=>{this.is_online||s(new Error(`Connection attempt to ${this.ip} timed out`))},e);const i=(e,s)=>{this.is_online=!0;for(const[e,t]of this.open_handlers)t();this.renew_subscriptions(),this.reconnect_automatically=!0,this.register_kw_listener({listener_id:"_towel_watch",kwl:"system.usrinfo",kw:"towel",defer_subscription:!1,execution_strategy:0,cache:!0,listener_type:0},n=>{this.m_current_towel={value:n,state:n===this.connection_pars.towel?1:0===n.length?2:0},this.connect_timer&&(t([e,s]),clearTimeout(this.connect_timer),this.connect_timer=null)}),this.send([{op:"readAll",kwl:"system.usrinfo",kw:["towel"]}])};this.web_socket.on_open(()=>{null!==this.reconnect_interval&&(clearInterval(this.reconnect_interval),this.reconnect_interval=null)}),this.web_socket.on_close(e=>{this.is_online=!1;for(const e in this.listeners)for(const t in this.listeners[e])Object.prototype.hasOwnProperty.call(this.listeners[e][t],"cached_value")&&(this.listeners[e][t].cached_value=void 0);null===this.reconnect_interval&&this.reconnect_automatically&&this.arm_reconnect_timer(),null!==n&&(clearTimeout(n),n=null);for(const[t,s]of this.close_handlers)s(e)}),this.web_socket.on_error(e=>{for(const[t,s]of this.error_handlers)s(e);!this.is_online&&this.reconnect_automatically&&this.arm_reconnect_timer()}),this.web_socket.on_message(e=>{this.handle_incoming(e,i)})}catch(e){s(e)}})}async initialize(s,n,i){const r="ws"===this.connection_pars.protocol?"http":"https";this.state={type:"awaiting-build-info",webserver_build_info:s,protocol_features:n};const o=(new Date).valueOf(),a=await t.download_json({ip:this.connection_pars.ip,protocol:r,port:this.connection_pars.port,path:"/data/build_info.json",reject_unauthorized:this.connection_pars.reject_unauthorized,timeout_ms:i}),l=(new Date).valueOf();let c=Math.max(50,i-(l-o));this.state={...this.state,type:"awaiting-schema",build_info:a};const h=a.commit.endsWith("+")?"|"+a.timestamp:"",_=a.commit+h,u=await d.schema_cache.retrieve({ip:this.connection_pars.ip,protocol:r,port:this.connection_pars.port,path:"/data/schema.json",key:_,reject_unauthorized:this.connection_pars.reject_unauthorized,timeout_ms:c});this.state={...this.state,type:"initializing"};const w=(new Date).valueOf();c=Math.max(500,i-(w-l));const p=await g.initialize(u.keywords,this,c),k=(new Date).valueOf();c=Math.max(500,i-(k-w));const m=await x.initialize(u,p,this,c);this.state={...this.state,annotated_schema:e.annotate(m,u),module_registry:p,runtime_constants:m,type:"ready"}}handle_incoming(e,t){var n,i;switch(this.m_expected_message_type){case 0:{const r=JSON.parse(e.data);null===(n=this.snoop_inbound_handler)||void 0===n||n.call(this,r);const o=r.length;for(let e=0;e<o;e++){const n=r[e];if(Object.prototype.hasOwnProperty.call(n,"kwl")){if(!Object.prototype.hasOwnProperty.call(n,"kw"))return;const e=this.listeners[n.kwl];for(const t in n.kw){const s=n.kw[t];for(const[e,i]of this.globalListeners)e(n.kwl,t,s);if(void 0!==e&&Object.prototype.hasOwnProperty.call(e,t)){const n=e[t];Object.prototype.hasOwnProperty.call(n,"cached_value")&&(n.cached_value=s);for(let e=0,t=Object.keys(n.handlers);e<t.length;++e){const i=n.handlers[t[e]];if(i)switch(i.execution_strategy){case 0:i.handler(s);break;case 1:this.pending_lazy_kw_updates[t[e]]={handler:i.handler,payload:s}}}}}}else if(Object.prototype.hasOwnProperty.call(n,"file"))this.m_expected_message_type="thumbnail_header"===n.file?1:3;else if(Object.prototype.hasOwnProperty.call(n,"thumbnail"))this.m_expected_message_type=2;else if(Object.prototype.hasOwnProperty.call(n,"marker")){s.assert("number"==typeof n.marker);const e=32767&n.marker;this.pending_markers.has(e)&&(this.pending_markers.get(e).resolve(),this.pending_markers.delete(e))}else Object.prototype.hasOwnProperty.call(n,"webserver_buildinfo")&&(Object.prototype.hasOwnProperty.call(n,"protocol_features")?(s.assert("object"==typeof n.protocol_features&&null!==n.protocol_features),t(n.webserver_buildinfo,{create_row_request_id:null!==(i=n.protocol_features.create_row_request_id)&&void 0!==i&&i})):t(n.webserver_buildinfo,{create_row_request_id:!1}))}}return;case 3:break;case 1:this.thumbnails&&(this.thumbnails.header_data=e.data);break;case 2:if(this.thumbnails&&(void 0===this.thumbnails.prev_data&&void 0!==this.thumbnails.header_data?this.thumbnails.prev_data=Buffer.concat([this.thumbnails.header_data,e.data]):(s.assert(void 0!==this.thumbnails.header_data),e.data.copy(this.thumbnails.prev_data,this.thumbnails.header_data.length)),this.thumbnails.prev_data))for(const[e,t]of this.thumbnails.handlers)t(this.thumbnails.prev_data);s.assert(e.data instanceof Buffer)}this.m_expected_message_type=0}}exports.VSocket=d,d.INTERVAL_SECS=1,d.schema_cache=new r.ResourceCache,d.s_timeout_scale=1;class w{constructor(e,t){this.socket=e,this.m_kwl=t,this.m_description=null}get description(){if(!this.m_description)if(null!==this.m_kwl)try{this.m_description=e.find_subtree(this.socket.schema,i.path_to_branch(this.kwl))}catch(e){throw new Error(`Invalid Subtree object: there is no subtree named '${this.kwl}'`)}else this.m_description=this.socket.schema.keywords;return this.m_description}get kwl(){if(null===this.m_kwl)throw new Error("Root objects do not have a keyword list name");return this.m_kwl}get parent(){return new w(this.socket,i.path_hd(this.kwl))}tableness(){return Array.isArray(this.description)?0:"subtree"===this.description.data_type&&"table_size"in this.description?this.description.named_rows?2:1:0}as_table(e){switch(this.tableness()){case 0:throw`${this.full_kwl()}@${this.socket.ip} is no table`;case 1:case 2:return new m(this.socket,this.kwl)}}table(e,t){return this.find(e).as_table()}as_named_table(e){switch(this.tableness()){case 0:case 1:throw`${this.full_kwl()}@${this.socket.ip} is no named table`;case 2:return new b(this.socket,this.kwl)}}named_table(e,t){return this.find(e).as_named_table()}get children(){return Array.isArray(this.description)?this.description:this.description.children}write_unchecked(e,t){this.socket.send([{op:"data",kwl:this.full_kwl(e.kwl),kw:{[e.kw]:t}}])}write_tree_unchecked(e,t){return this.socket.root.write_tree_unchecked(this.full_path(e),t)}read_unchecked(e,t){return this.socket.root.read_unchecked(this.full_path(e),t)}full_path(e){return{kw:e.kw,kwl:this.full_kwl(e.kwl)}}read(e,t){return this.socket.root.read(this.full_path(e),t)}write(e,t,s){return this.socket.root.write(this.full_path(e),t,s)}wait_until(e,t,s){return this.socket.root.wait_until(this.full_path(e),t,s)}update(e,t){return this.socket.root.update(this.full_path(e),t)}watch(e,t,s){return this.socket.root.watch(this.full_path(e),t,s)}deref(e,t){return this.socket.root.deref(this.full_path(e),t)}find(e,t){return new w(this.socket,this.full_kwl(e))}full_kwl(e){return e?`${this.kwl}.${e}`:this.kwl}}function p(e){switch(e){case"A":return 10;case"B":return 11;case"C":return 12;case"D":return 13;case"E":return 14;case"F":return 15;default:return+e}}exports.Subtree=w;class k extends w{constructor(e,t){super(e,"<root>"),this.socket=e,this.m_table_requests=t}async do_check(e,t,n){if(t&&!this.socket.module_registry.is_online(u(n)))throw new Error(`Unable to access ${n}@${this.socket.ip}: component ${u(n)} appears to be offline.`);if(e){switch(this.socket.current_towel.state){case 0:throw new Error(`Unable to write to ${this.socket.ip}: blocked by towel '${this.socket.current_towel.value}'.`);case 1:return;case 2:await this.socket.place_towel()}s.assert(1===this.socket.current_towel.state)}}do_check_readonly(e,t){if(e&&!this.socket.module_registry.is_online(u(t)))throw new Error(`Unable to access ${t}@${this.socket.ip}: component ${u(t)} appears to be offline.`)}async reboot(e){var t,s;await this.do_check(!0,!0,"system"),this.write_unchecked({kwl:"system",kw:"reboot"},null!==(t=null==e?void 0:e.command)&&void 0!==t?t:"reboot"),await i.pause_ms(d.scaledTimeout(1e3*(null!==(s=null==e?void 0:e.timeout)&&void 0!==s?s:20))),await this.socket.recovery({...e})}async reset(e){var t;await this.do_check(!0,!0,"system"),this.write_unchecked({kwl:"system",kw:"reset"},"reset"),await i.pause_ms(d.scaledTimeout(1e3*(null!==(t=null==e?void 0:e.timeout)&&void 0!==t?t:20))),await this.socket.recovery({...e})}async read(e,t){var s,n,i;return this.do_check_readonly(null!==(s=null==t?void 0:t.check_component_liveness)&&void 0!==s?s:this.socket.check_component_liveness,e.kwl),(null===(n=null==t?void 0:t.use_cache_if_present)||void 0===n||n)&&null!==(i=this.socket.query_cache(e.kwl,e.kw))&&void 0!==i?i:await this.read_unchecked(e,null==t?void 0:t.timeout)}async write(e,t,n){var r,o,a,l,c;await this.do_check(null!==(r=null==n?void 0:n.check_towel)&&void 0!==r?r:this.socket.check_towel_on_write,null!==(o=null==n?void 0:n.check_component_liveness)&&void 0!==o?o:this.socket.check_component_liveness,e.kwl);const h=e.kw.endsWith("_command")?e.kw.replace(/_command$/,"_status"):e.kw,_=(null==n?void 0:n.timeout)?d.scaledTimeout(1e3*n.timeout):d.scaledTimeout(),u=null!==(a=null==n?void 0:n.retry_interval_ms)&&void 0!==a?a:40;try{if("custom"===(null===(l=null==n?void 0:n.retry_until)||void 0===l?void 0:l.criterion)){let s=_/u;for(;s>0;){if(this.write_unchecked(e,t),await i.pause_ms(u),await n.retry_until.validator())return;s--}throw void 0}{this.write_unchecked(e,t);const i=setInterval(()=>{this.write_unchecked(e,t)},u);await this.wait_until({...e,kw:h},"status"===(null===(c=null==n?void 0:n.retry_until)||void 0===c?void 0:c.criterion)?e=>{var t;return null===(t=null==n?void 0:n.retry_until)||void 0===t?void 0:t.validator(e)}:e=>s.deepEqual(e,t),{check_component_liveness:!1,timeout:_/1e3}).finally(()=>clearInterval(i))}}catch(s){throw new Error(`Unable to change ${e.kwl}.${e.kw} @ ${this.socket.ip} to ${t}`)}}async wait_until(e,t,s){var n;this.do_check_readonly(null!==(n=null==s?void 0:s.check_component_liveness)&&void 0!==n?n:this.socket.check_component_liveness,e.kwl);const i=new Promise((n,i)=>{var r;const o=(null==s?void 0:s.timeout)?d.scaledTimeout(1e3*(null==s?void 0:s.timeout)):d.scaledTimeout();let a;const l=this.socket.register_kw_listener({kwl:e.kwl,kw:e.kw,execution_strategy:0,listener_type:0,defer_subscription:!1},e=>{!0===t(e)&&(c=!0,l.unregister(),a&&clearTimeout(a),n(e))});let c=!1;a=setTimeout(()=>{c||(l.unregister(),i(new Error(`wait_until(${this.full_kwl(e.kwl)}, ${e.kw}, ${t})@${this.socket.ip}: failed to satisfy the given criterion within ${Math.round(o/1e3)} s`)))},o),null!==(r=null==s?void 0:s.skip_initial_read)&&void 0!==r&&r||this.read(e,s)});return await i}async watch(e,t,s){var n,i;this.do_check_readonly(null!==(n=null==s?void 0:s.check_component_liveness)&&void 0!==n?n:this.socket.check_component_liveness,e.kwl);const r=this.socket.register_kw_listener({kwl:e.kwl,kw:e.kw,execution_strategy:0,listener_type:0,defer_subscription:null===(i=null==s?void 0:s.defer_subscription)||void 0===i||i},t);return new o.Watcher(e.kwl,e.kw,()=>{r.unregister()})}async update(e,t){var s;this.do_check_readonly(null!==(s=null==t?void 0:t.check_component_liveness)&&void 0!==s?s:this.socket.check_component_liveness,e.kwl);const n=new Promise((s,n)=>{var i;const r=(null==t?void 0:t.timeout)?d.scaledTimeout(1e3*(null==t?void 0:t.timeout)):d.scaledTimeout();let o;const a=this.socket.register_kw_listener({kwl:e.kwl,kw:e.kw,listener_type:1,execution_strategy:0,defer_subscription:null!==(i=null==t?void 0:t.defer_subscription)&&void 0!==i&&i},e=>{clearTimeout(o),s(e)});o=setTimeout(()=>{a.unregister(),n(new Error(`Received no update to ${this.full_kwl(e.kwl)}.${e.kw}@${this.socket.ip} within ${Math.round(r/1e3)} s`))},r)});return await n}async deref(e,t){var s;this.do_check_readonly(null!==(s=null==t?void 0:t.check_component_liveness)&&void 0!==s?s:this.socket.check_component_liveness,this.full_kwl(e.kwl));const n=await this.read(e);return n?new w(this.socket,n):null}async read_unchecked(e,t){const s=t?d.scaledTimeout(1e3*t):d.scaledTimeout();return new Promise((t,n)=>{let i;const r=this.socket.register_kw_listener({kwl:e.kwl,kw:e.kw,listener_type:1,execution_strategy:0,defer_subscription:!1},e=>{clearTimeout(i),t(e)});i=setTimeout(()=>{r.unregister(),n(new Error(`Unable to read ${e.kwl}.${e.kw} from ${this.socket.ip}`))},s+1e3),this.socket.send([{op:"readAll",kwl:e.kwl,kw:e.kw}])})}write_tree_unchecked(e,t){let s=t;const n=e.kwl.split(".");for(let e=n.length-1;e>=0;e--)s={kwl:{[n[e]]:s}};this.socket.send([{op:"tree",...s}])}write_unchecked(e,t){this.socket.send([{op:"data",kwl:e.kwl,kw:{[e.kw]:t}}])}async table_create_row(e,t){var n,i;await this.do_check(null!==(n=null==t?void 0:t.check_towel)&&void 0!==n?n:this.socket.check_towel_on_write,null!==(i=null==t?void 0:t.check_component_liveness)&&void 0!==i?i:this.socket.check_component_liveness,this.full_kwl(e));const r=void 0!==(null==t?void 0:t.index),o=void 0!==(null==t?void 0:t.name),a=this.m_table_requests.next_table_request_id;this.m_table_requests.next_table_request_id=(this.m_table_requests.next_table_request_id+1)%Math.pow(2,32);const l=!0===this.socket.protocol_features.create_row_request_id,c=(()=>{if(r||o||void 0!==(null==t?void 0:t.allow_reuse_row)||l){let e={};return r&&(e.index=t.index),o&&(e.name=t.name),void 0!==(null==t?void 0:t.allow_reuse_row)&&(e.allow_reuse_row=t.allow_reuse_row),l&&(e.request_id=a),e}return null})(),h=await new Promise(n=>{const i=(null==t?void 0:t.timeout)?d.scaledTimeout(1e3*(null==t?void 0:t.timeout)):d.scaledTimeout();let h;const _=this.socket.register_kw_listener({kwl:e,kw:"created_row",listener_type:0,execution_strategy:0,defer_subscription:!1},e=>{s.assert(null!==e),s.assert(Array.isArray(e));(!l||(s.assert(3===e.length),e[2]===a))&&(null===e[0]?(clearTimeout(h),n(null)):r&&(null==t?void 0:t.index)!==e[0]||o&&(null==t?void 0:t.name)!==e[1]||(clearTimeout(h),n([e[0],e[1]])))});this.socket.execute_pending_subscription_requests(),h=setTimeout(()=>{_.unregister(),n(null)},i),this.write_unchecked({kwl:e,kw:"create_row"},c)});if(null===h){const s=[...(null==t?void 0:t.index)?["index "+(null==t?void 0:t.index)]:[],...(null==t?void 0:t.name)?["named "+(null==t?void 0:t.name)]:[]],n=s.length>0?` (${s.join(", ")})`:"";throw new Error(`Unable to create row${n} @ table ${e}, ${this.socket.ip}`)}return h}async table_rename_row(e,t,s){try{await this.write({kwl:e,kw:"row_name_command"},t,s)}catch(s){throw new Error(`Unable to rename ${e} @ ${this.socket.ip} to ${t}`)}}async table_indices(e,t){var s;this.do_check_readonly(null!==(s=null==t?void 0:t.check_component_liveness)&&void 0!==s?s:this.socket.check_component_liveness,this.full_kwl(e));return function(e){const t=e.length/2;let s=[];for(let n=0;n<t;n++){const t=2*n;let i=8*n,r=p(e.charAt(t))+16*p(e.charAt(t+1));for(;r>0;)1==(1&r)&&s.push(i),r>>=1,i+=1}return s}(await this.read({kwl:e,kw:"rowMask"}))}async table_rows(e,t){return(await this.table_indices(e,t)).map(t=>`${e}[${t}]`)}async table_has_row(e,t,s){return(await this.table_indices(e,s)).indexOf(t)>=0}async table_delete_row(e,t,s){const n=this.socket.register_kw_listener({kwl:e,kw:"rowMask",cache:!0,defer_subscription:!1,listener_type:0,execution_strategy:0},()=>{});try{await this.write({kwl:`${e}[${t}]`,kw:"row_cmd"},"DELETE_ROW",{...s,retry_until:{criterion:"custom",validator:async()=>!await this.table_has_row(e,t)}})}catch(s){throw new Error(`Unable to delete ${e}[${t}] @ ${this.socket.ip}`)}finally{n.unregister()}}full_kwl(e){if(!e)throw new Error("Invalid path: kwl must be specified when accessing a root node");return e}}exports.Root=k;class m extends w{constructor(e,t){super(e,t)}async allocated_indices(e){return await this.socket.root.table_indices(this.kwl,e)}async is_allocated(e,t){return await this.socket.root.table_has_row(this.kwl,e,t)}async rows(e){return(await this.allocated_indices(e)).map(e=>this.row_unchecked(e))}row(e,t){return this.row_unchecked(e)}row_unchecked(e){return new y(this.socket,`${this.kwl}[${e}]`,e,this)}}exports.Table=m;class b extends m{constructor(e,t){super(e,t)}async create_row(e){const t=(await this.socket.root.table_create_row(this.kwl,e))[0];return this.row_unchecked(t)}async rows(e){return(await this.allocated_indices(e)).map(e=>this.row_unchecked(e))}row(e,t){return this.row_unchecked(e)}row_unchecked(e){return new v(this.socket,`${this.kwl}[${e}]`,e,this)}}exports.NamedTable=b;class y extends w{constructor(e,t,s,n){super(e,t),this.index=s,this.enclosing_table=n}}exports.TableRow=y;class v extends y{constructor(e,t,s,n){super(e,t,s,n),this.index=s,this.enclosing_table=n}async rename(e,t){await this.socket.root.table_rename_row(this.kwl,e,t)}async delete(e){await this.socket.root.table_delete_row(i.path_strip_trailing_index(this.kwl),this.index,e)}}var f;exports.NamedTableRow=v,function(e){e[e.Unknown=0]="Unknown",e[e.Disabled=1]="Disabled",e[e.Uninitialized=2]="Uninitialized",e[e.Running=3]="Running",e[e.Crashed=4]="Crashed"}(f=exports.ComponentState||(exports.ComponentState={}));class g{constructor(e,t){this.data={},this.sys_names={},this.change_handlers={},this.next_id=0;for(const t of e)this.sys_names[t.ua_name]=t.sys_name;this.data=t}translate_component_ua_name(e){if(this.sys_names.hasOwnProperty(e))return this.sys_names[e];throw new Error(`Unknown component '${e}'`)}on_change(e){const t=this.next_id.toString();return++this.next_id,this.change_handlers[t]=e,new h(3,t,()=>{delete this.change_handlers[t]})}static async initialize(e,t,s){let n={};for(const t of e)n[t.sys_name]={crashed:!1,pid:-1,owning_module:t.owning_module,ua_name:t.ua_name};let i=new g(e,n);const r="arkona_internal_module_registry",o=(e,t)=>e===g.DISABLED?f.Disabled:e<0?t?f.Crashed:f.Uninitialized:t?f.Crashed:f.Running;for(const s of e){const e=s.sys_name+"_pid";t.register_kw_listener({listener_id:"ModuleRegistry:"+e,kwl:r,kw:e,listener_type:0,execution_strategy:0,defer_subscription:!0},e=>{n[s.sys_name].pid=e;for(const e in i.change_handlers)i.change_handlers[e](s.sys_name,o(n[s.sys_name].pid,n[s.sys_name].crashed))});const a=s.sys_name+"_crashed";t.register_kw_listener({listener_id:"ModuleRegistry:"+a,kwl:r,kw:a,listener_type:0,execution_strategy:0,defer_subscription:!0},e=>{n[s.sys_name].crashed=e;for(const e in i.change_handlers)i.change_handlers[e](s.sys_name,o(n[s.sys_name].pid,n[s.sys_name].crashed))})}return await new Promise((e,a)=>{const l=setTimeout(()=>{const e=new Set;for(const t in n)if("software_update"!==t)switch(o(n[t].pid,n[t].crashed)){case f.Uninitialized:case f.Crashed:e.add(n[t].owning_module)}a(new Error(`Unable to initialize module registry @ ${t.ip}: request timed out while waiting for the following modules: ${[...e].join(", ")}`))},s),c=i.on_change((t,s)=>{let i=!0;for(const e in n)if(o(n[e].pid,n[e].crashed)==f.Uninitialized&&"software_update"!==e){i=!1;break}i&&(c.unregister(),clearTimeout(l),e())});for(const e in n)t.root.read_unchecked({kwl:r,kw:e+"_pid"}).catch(e=>a(e)),t.root.read_unchecked({kwl:r,kw:e+"_crashed"}).catch(e=>a(e))}),i}is_online(e){return this.data[e].pid>0&&!1===this.data[e].crashed}is_disabled(e){return this.data[e].pid===g.DISABLED}get_status(e){return{pid:this.data[e].pid,crashed:this.data[e].crashed}}}exports.ModuleRegistry=g,g.DISABLED=-2;class x{constructor(e){this.data={},this.data=e}find_constant(e,t){var s;return null===(s=this.data[i.snake_case(e)])||void 0===s?void 0:s[t]}get_constant(e,t){const s=this.find_constant(e,t);if(void 0===s)throw new Error(`Unknown runtime constant ${e}.${t}`);return s}equal(e){const t=Object.keys(this.data).sort(),s=Object.keys(e.data).sort();if(t.length!==s.length)return!1;for(let n=0;n<t.length;++n){if(t[n]!==s[n])return!1;const i=t[n],r=Object.keys(this.data[i]).sort(),o=Object.keys(e.data[i]).sort();if(r.length!==o.length)return!1;for(let t=0;t<r.length;++t){if(r[t]!==o[t])return!1;const s=r[t];if(this.data[i][s]!==e.data[i][s])return!1}}return!0}static async initialize(e,t,s,n){return new Promise((r,o)=>{const a={};let l=setTimeout(()=>{o(new Error(`Unable to obtain runtime constants from ${s.ip}: attempt timed out`))},n);const c={},h=e=>{const s=e.split("::");return{component_sys_name:t.translate_component_ua_name(s[0]),constant_name:s[1]}},_=t=>{var s;for(const n of e.keywords)if(n.sys_name===t)return(null!==(s=n.bound_to)&&void 0!==s?s:[]).map(h);throw new Error("Unknown component "+t)};for(const s in e.constants){const n=t.translate_component_ua_name(s);a[n]={};const i=Object.keys(e.constants[s]);c[n]={missing_constants:_(n),own_constants:i}}(async()=>{var e;const t=new i.WorkQueue({num_workers:32});let n=!1;for(;Object.keys(c).length>0&&!n;){const i=Object.keys(c);for(const r of i){let i="read";for(const t of c[r].missing_constants){const s=null===(e=null==a?void 0:a[t.component_sys_name])||void 0===e?void 0:e[t.constant_name];if(void 0===s){i="wait";break}if(!1===s){i="discard";break}}switch(i){case"wait":break;case"discard":delete c[r];break;case"read":{const e=r+".runtime_constants";for(const i of c[r].own_constants)t.push(()=>s.root.read_unchecked({kwl:e,kw:i}).then(e=>{a[r][i]=e},e=>{n=!0,o(e)}));delete c[r]}}}await t.drain().catch(e=>{n=!0,o(e)})}})().then(()=>{clearTimeout(l),r(new x(a))},e=>o(e))})}}exports.RuntimeConstants=x;