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) { } } } }