
/*=============================================================================================
	author:ZhaoJun
	version:1.2
	email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
'use strict';
/*-------------------------------------------------------------------------------------------*/
const queue=$Sys.model('/db/redis')

// 分布式事务请求操作
/*-------------------------------------------------------------------------------------------*/	
    class transaction
    {	

        //循环处理失败的，继续发送（事务发送方）
        async loop()
        {
            let retry=this.retry
            let retryBack=this.retryBack
            let retryTime=this.retryTime
            let db=this.db
            let name=this.name
            let count=this.count
            let user=$Config.info.mac
            let keyBack=this.keyBack
            let make=this.make
            
            let send = this.send()
            let ack = this.ack()

            if(!make)
            {
                $Time.task.push
                (
                    {
                        "type":"ms","init":0,"match":retryTime,"fun":async ()=>
                        {
                            let arr
                            if(!make)
                            {
                                arr=retry()
                                send(arr)
                            }
                            else
                            {
                                arr=retryBack()
                                ack(arr)
                            }
                        }
                    }
                )   
            }

            while (true) 
            {
                try 
                {
                    if(!make)
                    {
                        let data=await queue.queueXreadgroup({keyBack,name,user,count,timeout:0,db})
                        await this.affirm(data)
                        console.log(data,1)
                    }
                    else
                    {
                        let data=await queue.queueXreadgroup({key,name,user,count,timeout:0,db})
                        data=await this.check(data)
                        await this.make(data)
                        console.log(data,2)
                    }
                } 
                catch (error) 
                {
                    console.error('[分布式事务]发生错误',error)
                }   
                
            }
        }

        makeArr (arr)
        {
            if(arr instanceof Object)
            {
                return JSON.stringify(arr)
            }
        }

        com(arr,key)
        {
            let db=this.db
            let max=this.max
            let retryListLimit=this.retryListLimit

			if(arr)
            {
                let back
                if(Array.isArray(arr))
                {
                    arr=arr.slice(0,retryListLimit)
                    let backList=[]
                    for (let index = 0; index < arr.length; index++) 
                    {
                        let cur=arr[index]
                        back=this.makeArr(cur)
                        backList.push(index)
                        backList.push(back)
                    }
                    queue.queueXadd({key,max,list:backList,db})
                }
                else if(back=this.makeArr(arr))
                {
                    queue.queueXadd({key,max,list:[0,back],db})
                }
            }
        }
        
        //发送事务，数组会重组发送到队列,数据为json对象（事务发送方）
		async send(arr)
		{
            this.com(arr,this.key)
        }

        //检测需重新发送的事务，返回是数组的话会分开发送到队列（事务发送方，需重写）
        //可在这一层，储存重试了几次了，超过重试次数，标记为失败
        async retry(){}
        

        //确认被处理（事务发送方，需重写）
        async affirm(arr){}

        //处理事务（事务处理方，需重写）
        async make(arr){}
        
        //检测是否处理过,处理了，回复以处理的消息，没出处理，处理了回复（事务处理方，需重写）
        async check(arr){}

        //确认处理（事务处理方）
        async ack(arr)
        {
            this.com(arr,this.keyBack)
        }

        //确认处理（事务处理方，事务发送方，需传参）
        async init({retry,retryTime=1000*10,key='transaction',keyBack='transactionBack',make=false,
        db='main',name='node',count=1,max=10000000,retryListLimit=10,affirm,check})
        {
            if(!(retry && affirm && check && make))
            {
                console.warn('[分布式事务]','请传入初始化参数')
                return
            }
            this.retryTime=retryTime

            this.retry=retry
            this.affirm=affirm
            this.check=check
            this.make=make
            this.retryListLimit=retryListLimit
            this.key=key
            this.db=db
            this.max=max
            this.name=name
            this.count=count
            this.keyBack=keyBack
            this.make=make

            this.loop()
        }
		
    }
/*-------------------------------------------------------------------------------------------*/    
module.exports=transaction;
