using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LolDataRequestLib
{
///
/// 실시간으로 업데이트를 해야하는 데이터들의 추상팩토리클래스.
///
internal abstract class ARequestData
{
///
/// DB Access 클라이언트.
///
protected MongoClient mDBClient = new MongoClient(DBDefine.MONGODB주소);
///
/// DB데이터베이스.
///
protected IMongoDatabase eventDataBase = null;
///
/// 가장 최근에 업데이트했던 데이터의 인덱스.
/// 같은 데이터를 계속 업데이트 하는 것을 막는다.
///
protected int mLastDataSequanceIndex = 0;
///
/// 데이터를 가져올 DB 컬렉션(테이블) 이름
///
protected string mCollectionName = "";
///
/// db에서 가져와서 manager에 업데이트하기위해 가공된 BsonValue
///
protected BsonValue mUpdatedBsonValue = null;
///
/// 인스턴스를 생산하기위해 요청된 데이터타입.
///
protected DBDefine.RequestDataType mRequestType = DBDefine.RequestDataType.BAN_AND_PICK;
///
/// 팩토리 Create메서드
///
///
///
internal static ARequestData createRequestFactory(DBDefine.RequestDataType recvRequestType)
{
ARequestData bufInstance = null;
try
{
switch (recvRequestType)
{
case DBDefine.RequestDataType.BAN_AND_PICK:
bufInstance = new BanPickRequest();
bufInstance.mCollectionName = "champ_select";
break;
case DBDefine.RequestDataType.GAME_STATUS:
bufInstance = new GameStatusRequest();
bufInstance.mCollectionName = "stats_update";
break;
case DBDefine.RequestDataType.OBJECT_EVENT:
bufInstance = new ObjectDataRequest();
bufInstance.mCollectionName = "epic_monster_kill";
break;
case DBDefine.RequestDataType.STRUCT_EVENT:
bufInstance = new StructDataRequest();
bufInstance.mCollectionName = "building_destroyed";
break;
case DBDefine.RequestDataType.DRAGON_RESPAWN:
bufInstance = new DragonRequest();
bufInstance.mCollectionName = "queued_dragon_info";
break;
case DBDefine.RequestDataType.ATAKHAN_RESPAWN:
bufInstance = new AtakhanRequest();
bufInstance.mCollectionName = "queued_epic_monster_info";
break;
case DBDefine.RequestDataType.STRUCT_GOLD_EVENT:
bufInstance = new StructGoldDataRequest();
bufInstance.mCollectionName = "building_gold_grant";
break;
}
//조회를 위한 RequestType등록.
bufInstance.mRequestType = recvRequestType;
//데이터베이스(Schema)선택
bufInstance.eventDataBase = bufInstance.mDBClient.GetDatabase("datalol");
//ThreadPool에 업데이트워크를 등록
ThreadPool.QueueUserWorkItem(o => { bufInstance.UpdateWorker(); });
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return bufInstance;
}
///
/// 인스턴스의 DB주소를 변경
/// 20210614 현재 사용하지 않는다.
/// Mongodb의 커넥션 인스턴스가 Mariadb와 달라서 비슷하게 접근했다가 Connection이 Disconnect되는 현상이 계속 발생했다.
///
internal void resetDBAddress()
{
mDBClient = new MongoClient(DBDefine.MONGODB주소);
}
///
/// 업데이트 인덱스를 초기화한다.
/// 20210608 첫용이 업데이트 되지 않는 버그를 수정하면서 추가.
///
internal void initIndex()
{
this.mLastDataSequanceIndex = 0;
}
///
/// 인스턴스내에 데이터를 업데이트 하는 워커메서드.
/// 해당메서드를 스레드풀에 넣고 반복문을 통해 계속 업데이트한다.
///
internal void UpdateWorker()
{
while (DataManager.getInstance().IsupdateWorkersWork)
{
try
{
//DB에서 데이터를 가져온다.
this.requestDataMongoDB();
//조회되는 데이터가 없을경우 테이블을 비운다.
if (mUpdatedBsonValue == null)
{
this.exchangeTable();
}
//조회되는 데이터가 기존 데이터와 INDEX가 같지 않을경우 데이터를 업데이트한다.
else if (mUpdatedBsonValue["sequenceIndex"].ToInt32() != this.mLastDataSequanceIndex)
{
this.exchangeTable();
this.mLastDataSequanceIndex = mUpdatedBsonValue["sequenceIndex"].ToInt32();
}
//조회 후 인터벌 시간동안 슬립.
Thread.Sleep(DataManager.getInstance().리퀘스트인터벌밀리초);
}
catch (Exception ex)
{
//DataManager.getInstance().mCallback.errorReceivedByWorker(요청데이터, ex.ToString());
//break;
#if(DEBUG)
{
Console.WriteLine(ex.ToString());
}
#endif
}
}
}
///
/// DB에서 데이터를 요청하는 메서드.
///
protected virtual void requestDataMongoDB()
{
try
{
//var filter = Builders.Filter.Eq("RequestGameID", DataManager.getInstance().mPlatformGameID);
var projection = Builders.Projection
.Exclude("_id")
.Include("eventDocument");
List documents = eventDataBase.GetCollection(this.mCollectionName)
.Find(new BsonDocument())//.Find(filter)
.SortByDescending(x => x["sequenceIndex"])
.Project(projection)
.Limit(1)
.ToList();
if (documents.Count != 0)
{
mUpdatedBsonValue = documents.Last()["eventDocument"];
}
else
{
mUpdatedBsonValue = null;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void exchangeTable()
{
try
{
Dictionary bufHash = null;
switch (this.mRequestType)
{
case DBDefine.RequestDataType.BAN_AND_PICK:
DataManager.getInstance().밴픽데이터 = this.mUpdatedBsonValue;
break;
case DBDefine.RequestDataType.GAME_STATUS:
DataManager.getInstance().경기데이터 = this.mUpdatedBsonValue;
//DataManager.getInstance().경기시간 = this.mUpdatedBsonValue["gameTime"].ToInt32() / 1000;
//Console.WriteLine("gametime : " + this.mUpdatedBsonValue["gameTime"].ToInt32() / 1000);
break;
case DBDefine.RequestDataType.OBJECT_EVENT:
DataManager.getInstance().오브젝트데이터 = this.mUpdatedBsonValue;
break;
case DBDefine.RequestDataType.STRUCT_EVENT:
DataManager.getInstance().건물데이터 = this.mUpdatedBsonValue;
break;
case DBDefine.RequestDataType.DRAGON_RESPAWN:
DataManager.getInstance().드래곤리스폰 = this.mUpdatedBsonValue;
break;
case DBDefine.RequestDataType.STRUCT_GOLD_EVENT:
DataManager.getInstance().타워골드데이터 = this.mUpdatedBsonValue;
break;
//case DBDefine.RequestDataType.ATAKHAN_RESPAWN:
// DataManager.getInstance().아타칸리스폰 = this.mUpdatedBsonValue;
// break;
}
}
catch(Exception ex) { }
}
}
}