宁卫免费PBX中的排队机空闲分机搜询策略
在以前,我们是在c代码中使用了若干条命令去查询一个空闲的座席,但是发现那样存在若干问题:
1. 效率慢。
2. 在大并发情况下,锁加的多就会影响体验,锁加少了,会出现话机冲突。
3. c语言中改逻辑性的东西,挺头痛。所以把其改为PostgreSQL的function,即存储过程来使用,因为这部分都是离线部署的,所以触发器和存储过程是任一用户都可以看到的,故而把源代码分享出来。
表名和表结构就不列出来了,在数据库中都有,只列出存储过程的代码:
drop function get_group_idle_ext_first;--get_group_idle_ext_first用于查找第一个空闲的座席分机--p_use_multi_domain 是不是使用多租户--p_callin_number 呼入号码--p_group_number 组名或组短号,但可以带domain--p_transfer_times 呼转次数,第一次会考虑以前是谁接的,那么本次优先他--p_use_agent_status 是否要使用座席状态,如置忙、置闲,迁入迁出(上线下线)等,1为需要,0为不需要,放在这里,也可以允许使用者自己手工更改CREATE FUNCTION get_group_idle_ext_first(IN p_use_multi_domain BOOLEAN,IN p_callin_number TEXT,IN p_group_number TEXT,IN p_transfer_times int,IN p_use_agent_status int)RETURNS TABLE( myext text, mytimeout INT, mypassed BOOLEAN)LANGUAGE 'plpgsql'COST 100VOLATILE PARALLEL UNSAFEAS $BODY$DECLAREf_mode int;f_timeout int;f_domain TEXT;f_group_number TEXT;f_position int;f_sql TEXT;f_c_split TEXT;f_use_agent_status int;--------r_passed BOOLEAN;r_ext Text;r_timeout int;----v_record RECORD;BEGINr_passed := false;f_c_split := '@';if (p_use_multi_domain =true) thenf_group_number := p_group_number;f_position := strpos(f_group_number,'@'); --postition(f_c_split in f_group_number);if (f_position = 0) thenf_group_number := p_group_number;f_domain := 'default';elsef_group_number := substring(p_group_number from 1 for f_position-1);f_domain := substring(p_group_number from f_position+1 for char_length(p_group_number)-f_position );end if;elsef_group_number := p_group_number;f_domain := 'default';end if;f_mode := -1;if (p_use_agent_status =1) thenf_use_agent_status :=1;elsef_use_agent_status :=0;end if;raise notice 'group_number is %',f_group_number;raise notice 'domain is %',f_domain;---------------------------------if (p_use_multi_domain = true) thenf_sql := 'select a.queue_mode,a.group_callout_timeout from nway_ext_group a,nway_fs_domains b where a.group_number=''' || f_group_number || ''' and a.domain_id=b.id and b.domain_name=''' || f_domain || ''';';elsef_sql := 'select queue_mode ,group_callout_timeout from nway_ext_group wheregroup_number=''' || f_group_number || ''';';end if;raise notice 'group sql:%',f_sql;EXECUTE f_sql INTO f_mode,f_timeout;raise notice 'mode:%, timeout:%',f_mode,f_timeout;if (f_mode is NULL) thenraise notice 'data is null';r_timeout := -1;r_ext := 'error:not found group';else if (f_mode < 0) then--return r_passed;r_timeout := -1;r_ext := 'mode not support';else--执行后续if (f_timeout is NULL) thenr_timeout = 15;elser_timeout = f_timeout;end if;if (f_mode >2 and p_transfer_times = 0) thenif (p_use_multi_domain = true) thenif (f_use_agent_status =1) thenf_sql := 'SELECT extension_number FROM nway_extension where reg_state=''reged'' and agent_status=''idle'' and ' ||' call_state=''ready'' and extension_number = ' ||' (select agent_number from nway_call_remember where call_number=''' || p_callin_number ||''' and group_number=''' || f_group_number || ''' and domain_name=''' || f_domain || ''' order by insert_time desc limit 1 );';elsef_sql := 'SELECT extension_number FROM nway_extension where reg_state=''reged'' ' ||' and call_state=''ready'' and extension_number = ' ||' (select agent_number from nway_call_remember where call_number=''' || p_callin_number ||''' and group_number=''' || f_group_number || ''' and domain_name=''' || f_domain || ''' order by insert_time desc limit 1 );';end if;elseif (f_use_agent_status =1) thenf_sql := 'SELECT extension_number FROM nway_extension where reg_state=''reged'' and agent_status=''idle'' and call_state=''ready''' ||' and extension_number = (select agent_number from nway_call_remember where call_number=''' ||p_callin_number ||''' and group_number=''' || f_group_number || ''' order by insert_time desc limit 1 );';elsef_sql := 'SELECT extension_number FROM nway_extension where reg_state=''reged'' and call_state=''ready''' ||' and extension_number = (select agent_number from nway_call_remember where call_number=''' ||p_callin_number ||''' and group_number=''' || f_group_number || ''' order by insert_time desc limit 1 );';end if;end if;raise notice 'last agent sql:%',f_sql;EXECUTE f_sql INTO r_ext;end if;------if (r_ext is NULL OR char_length(r_ext) <2) thenRAISE NOTICE 'search idle agent from talbe:%',p_callin_number;if (p_use_multi_domain = true) thenif (f_use_agent_status =1) thenif (f_mode=3 OR f_mode = 0) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'')' ||' and (c.call_state=''ready'' OR c.call_state=''READY'') and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'')' ||' and s.id=e.domain_id and s.domain_name=''' || f_domain || ''' and (e.group_number=''' ||f_group_number || ''') and '||' (c.extension_number in ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''' )) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1;';end if;if (f_mode=1 OR f_mode = 4) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'')'||' and (c.call_state=''ready'' OR c.call_state=''READY'') and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'')'||' and s.id=e.domain_id and s.domain_name=''' || f_domain ||''' and (e.group_number=''' ||f_group_number || ''') and (c.extension_number in ' ||' ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by random() limit 1;';end if;if (f_mode = 2 OR f_mode =5) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and' ||' (c.call_state=''ready'' OR c.call_state=''READY'') and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'')'||' and s.id=e.domain_id and s.domain_name=''' || f_domain ||''' and (c.extension_number >e.current_ext_number) and (e.group_number=''' || f_group_number ||''') and (c.extension_number in ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''' )) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1;';end if;elseif (f_mode=3 OR f_mode = 0) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'')' ||' and (c.call_state=''ready'' OR c.call_state=''READY'')' ||' and s.id=e.domain_id and s.domain_name=''' || f_domain || ''' and (e.group_number=''' ||f_group_number || ''') and '||' (c.extension_number in ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''' )) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1;';end if;if (f_mode=1 OR f_mode = 4) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'')'||' and (c.call_state=''ready'' OR c.call_state=''READY'') '||' and s.id=e.domain_id and s.domain_name=''' || f_domain ||''' and (e.group_number=''' ||f_group_number || ''') and (c.extension_number in ' ||' ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by random() limit 1;';end if;if (f_mode = 2 OR f_mode =5) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and' ||' (c.call_state=''ready'' OR c.call_state=''READY'') '||' and s.id=e.domain_id and s.domain_name=''' || f_domain ||''' and (c.extension_number >e.current_ext_number) and (e.group_number=''' || f_group_number ||''') and (c.extension_number in ( select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''' )) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1;';end if;end if;elseif (f_use_agent_status =1) thenif (f_mode=3 OR f_mode = 0) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'')'||' and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'') and (e.group_number=''' ||f_group_number ||''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number ||''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1; ';end if;if (f_mode=1 OR f_mode = 4) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'') '||' and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'') and (e.group_number=''' ||f_group_number ||''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number ||''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by random() limit 1; ';end if;if (f_mode = 2 OR f_mode =5) then--from e.current_ext_numberf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'')' ||' and (c.agent_state=''up'' OR c.agent_state=''UP'') and (c.agent_status=''ready'' OR c.agent_status=''idle'') and (c.extension_number >e.current_ext_number)'||' and (e.group_number=''' ||f_group_number ''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number || ''')) and '||'(extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1; ';end if;elseif (f_mode=3 OR f_mode = 0) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'')'||' and (e.group_number=''' ||f_group_number ||''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number ||''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1; ';end if;if (f_mode=1 OR f_mode = 4) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'') '||' and (e.group_number=''' ||f_group_number ||''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number ||''')) and (extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by random() limit 1; ';end if;if (f_mode = 2 OR f_mode =5) then--from e.current_ext_numberf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and (c.call_state=''ready'' OR c.call_state=''READY'')' ||' and (c.extension_number >e.current_ext_number)'||' and (e.group_number=''' ||f_group_number ''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number || ''')) and '||'(extract(epoch FROM (now()-c.last_state_change_time)) >1 ) order by c.extension_number limit 1; ';end if;end if;end if;raise notice 'agent sql:%',f_sql;EXECUTE f_sql INTO r_ext;if (r_ext is NULL) thenr_passed := false;r_ext := '';raise notice 'not found idle extension';r_timeout=0;if (f_mode = 2 OR f_mode =5) thenif (p_use_multi_domain = true) thenf_sql := 'select c.extension_number from nway_extension c,nway_ext_group e,nway_fs_domains s where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and ' ||' (c.call_state=''ready'' OR c.call_state=''READY'') and (c.seat_state=''up'' OR c.seat_state=''UP'') and (c.seat_status=''ready'' OR c.seat_status=''idle'') ' ||' and s.id=e.domain_id and s.domain_name=''' || f_domain || ''' and (e.group_number=''' || f_group_number ||''') and (c.extension_number in (select m.ext from nway_ext_group_map m, nway_ext_group n,nway_fs_domains p where n.group_number=''' || f_group_number ||''' and n.id =m.ext_group_id and n.domain_id=p.id and p.domain_name=''' || f_domain || ''' )) order by c.extension_number limit 1;';elsef_sql := 'select c.extension_number from nway_extension c,nway_ext_group e where (c.reg_state=''reged'' OR c.reg_state=''REGED'') and '||' (c.call_state=''ready'' OR c.call_state=''READY'') and (c.seat_state=''up'' OR c.seat_state=''UP'') and (c.seat_status=''ready'' OR c.seat_status=''idle'') '||' and (e.group_number=''' || f_group_number || ''') and (c.extension_number in ( select ext from nway_ext_group_map where ext_group_number=''' || f_group_number ||''')) order by c.extension_number limit 1;';end if;raise notice 'mode 2or5 repeat sql:%',f_sql;EXECUTE f_sql INTO r_ext;if (r_ext is NULL ) thenr_passed = false;elser_passed = true;end if;end if;elseraise notice 'found idle extension';r_passed = true;end if;elser_passed := true;end if;end if;end if;if (r_passed = true) thenif (p_use_multi_domain = true) thenf_sql := 'update nway_extension set call_state=''callout'',last_state_change_time=now() where extension_number ='''|| r_ext ||''' and domain_id=(select id from nway_fs_domwains where domain_name='''|| f_domain || ''');';elsef_sql :='update nway_extension set call_state=''callout'',last_state_change_time=now() where extension_number ='''|| r_ext ||''';';end if;raise notice 'found ext:% !!! and set it callout sql:%',r_ext,f_sql;EXECUTE f_sql;if (p_use_multi_domain = true) thenf_sql := 'update nway_ext_group set current_ext_number=''' || r_ext|| ''' where group_number =''' || f_group_number || ''' and domain_id in (select id from nway_fs_domains where domain_name='''|| f_domain || ''');';elsef_sql :='update nway_ext_group set current_ext_number=''' || r_ext|| ''' where group_number =''' || f_group_number || ''';';end if;raise notice 'set ext:% is current using extension for group sql:%',r_ext,f_sql;EXECUTE f_sql;if (p_use_multi_domain = true ) thenmyext := r_ext || '@' || f_domain;elsemyext := r_ext;end if;elsemyext := '';end if;mypassed := r_passed;mytimeout := r_timeout;return query select myext,mytimeout,mypassed;END;$BODY$;select public.get_group_idle_ext_first(true,'18621575908','110@nway.com',0,1);
宁卫通信