package com.orderpay
import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.co.{CoProcessFunction, KeyedCoProcessFunction}
import org.apache.flink.streaming.api.scala._
import org.apache.flink.util.Collector
//实时对账
case class ReceiveEvent(txId:String,payChannel:String,timestamp:Long)
object TxMatch {
def main(args: Array[String]): Unit = {
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val inputStream: DataStream[String] = env.readTextFile(“in/OrderLog.csv”)
val orderStream: KeyedStream[OrderEvent, String] = inputStream.map(
data => {
val arr: Array[String] = data.split(",")
OrderEvent(arr(0).toLong, arr(1), arr(2), arr(3).toLong)
}
).assignAscendingTimestamps(.timestamp * 1000L)
.filter(.eventType==“pay”)
.keyBy(.txId)
//读取到账事假
val receiveinputStream: DataStream[String] = env.readTextFile(“in/ReceiptLog.csv”)
val receiverStream: KeyedStream[ReceiveEvent, String] =receiveinputStream.map(
data => {
val arr: Array[String] = data.split(",")
ReceiveEvent(arr(0), arr(1), arr(2).toLong)
}
).assignAscendingTimestamps(.timestamp * 1000)
.keyBy(_.txId)
//合流操作 进行处理
val resultStream: DataStream[(OrderEvent, ReceiveEvent)] = orderStream.connect(receiverStream)
.process(new TxPayMatchResult())
resultStream.print(“result”)
resultStream.getSideOutput(new OutputTagOrderEvent).print(“unmatched-pay”)
resultStream.getSideOutput(new OutputTagReceiveEvent).print(“unmatched-received”)
env.execute()
}
}
class TxPayMatchResult() extends CoProcessFunction[OrderEvent,ReceiveEvent,(OrderEvent,ReceiveEvent)]{
//定义状态 保存当前交易对应的订单支付事件和到账事件
lazy val payEventState: ValueState[OrderEvent] = getRuntimeContext.getState(new ValueStateDescriptorOrderEvent)
lazy val receiveEventState: ValueState[ReceiveEvent] = getRuntimeContext.getState(new ValueStateDescriptorReceiveEvent)
//订单支付事件 判断是否有到账事件
override def processElement1(pay: OrderEvent, ctx: CoProcessFunction[OrderEvent, ReceiveEvent, (OrderEvent, ReceiveEvent)]#Context, out: Collector[(OrderEvent, ReceiveEvent)]): Unit = {
val receipt: ReceiveEvent = receiveEventState.value()
if(receipt != null){
//到账
out.collect(pay,receipt)
}else{
//如果还没嘞
ctx.timerService().registerEventTimeTimer(pay.timestamp*1000L+5000L)
//更新状态
payEventState.update(pay)
}
}
override def processElement2(receipt: ReceiveEvent, ctx: CoProcessFunction[OrderEvent, ReceiveEvent, (OrderEvent, ReceiveEvent)]#Context, out: Collector[(OrderEvent, ReceiveEvent)]): Unit = {
val pay: OrderEvent = payEventState.value()
if(pay != null){
//到账 判断支付事件
out.collect(pay,receipt)
}else{
//如果还没嘞
ctx.timerService().registerEventTimeTimer(receipt.timestamp*1000L+3000L)
//更新状态
payEventState.update(pay)
}
}
private val unmatchedpay = new OutputTagOrderEvent
private val unmatchedreceived = new OutputTagReceiveEvent
override def onTimer(timestamp: Long, ctx: CoProcessFunction[OrderEvent, ReceiveEvent, (OrderEvent, ReceiveEvent)]#OnTimerContext, out: Collector[(OrderEvent, ReceiveEvent)]): Unit = {
//1.
//2.定时器触发 判断状态中哪个还存在 就代表另一个每来
//定义侧输出流 报警提示
if(payEventState.value() != null){
ctx.output(unmatchedpay,payEventState.value())
}
if(receiveEventState.value() != null){
ctx.output(unmatchedreceived,receiveEventState.value())
}
//清空状态
payEventState.clear()
receiveEventState.clear()
}
}