在实际业务中,我们每次登录后,可能需要在服务端维护一些设备相关的资源信息,而不同设备所需维护的资源信息又不尽相同。Khala提供了设备资源的维护储存功能,在此我们通过一个具体的业务中对其进行展示。
一个用户聊天设备,用户可以新添加好友ID,也可以查询当前已经添加的所有好友ID,因此服务端应该为登录设备记录和维护当前好友id。但是在khala的默认实现中,当前好友id这种与业务紧密联系的信息显然是没有直接提供接口的。但是khala提供了一个extraContext的接口,此接口通过boost库中的any类型实现,可以借此维护不同设备资源信息。具体业务实现如下:
我们依旧在之前实现的MyUsrType类型下进行修改。首先我们实现一个用户设备资源类UsrInfo,在这个类中,我们通过set维护好友id,并提供添加和查询好友ID的接口。在UsrInfo的析构函数中,我们通过打印日志来跟踪资源对象的生命周期。
class UsrInfo { public: UsrInfo(const std::string& name) : name_(name) { } virtual ~UsrInfo() { LOG_INFO << "UsrInfo name:" << name_ << " is destructed!"; } //添加一个好友的ID void addFriends(uint id) { myFriends_.insert(id); } //获取所有好友的IDs std::vector<uint> getAllFriends() { std::vector<uint> friends; friends.assign(myFriends_.begin(), myFriends_.end()); return friends; } const std::string& getName() const { return name_; } private: //当前用户名 std::string name_; //当前用户添加的好友IDs11 std::set<uint> myFriends_; };
在MyUsrType的onLoginSuccessMsg中,我们申请UsrInfo资源,并将其指针保存到infoNodePtr的ExtraContext中。在实际运用中,我们可以通过使用智能指针shared_ptr来对申请的资源UsrInfo进行管理,那ExtraContext保存的将为UsrInfo的智能指针。
bool MyUsrType::onLoginSuccessMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time) { std::string name = msg[KEY_LOGIN_NAME].asString(); //将申请的UsrInfo指针保存到ExtraContext infoNodePtr->setExtraContext(new UsrInfo(name)); std::stringstream ss; ss << "login success! your id is:" << infoNodePtr->getId(); infoNodePtr->send(ss.str()); return true; }
我们可以给MyUsrType创建addFriend和getFriends两个消息事件,具体添加方法参见5、登录管理设备类型 + 创建新的设备类型,在这两个消息事件的实现中,我们通过ExtraContext获取UsrInfo的资源,并读写该资源信息。
bool MyUsrType::onAddFriend(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time) { uint friendId = msg[KEY_FRIEND_ID].asUInt(); //尝试获取UsrInfo资源 UsrInfo* usrInfo = boost::any_cast<UsrInfo*>( infoNodePtr->getExtraContext()); if (usrInfo == 0) return false; //写UsrInfo资源 usrInfo->addFriends(friendId); std::stringstream ss; ss << "add friend id:" << friendId << " success !"; infoNodePtr->send(ss.str()); return true; } bool MyUsrType::onGetFriends(khala::InfoNodePtr& infoNodePtr, Json::Value& msg, khala::Timestamp time) { //尝试获取UsrInfo资源 UsrInfo* usrInfo = boost::any_cast<UsrInfo*>( infoNodePtr->getExtraContext()); if (usrInfo == 0) return false; //读取UsrInfo资源中的信息 std::vector<uint> friends = usrInfo->getAllFriends(); std::stringstream ss; ss<<"my friends id:"; std::vector<uint>::iterator it = friends.begin(); for(;it!=friends.end();it++){ ss<<*it<<" "; } infoNodePtr->send(ss.str()); return true; }
因为UsrInfo资源是我们在维护MyUsrType类型的设备的生命周期中申请的资源,因此当该设备退出生命周期将要结束时,我们必须将申请的UsrInfo资源释放。设备资源的释放工作在releaseConnNode中进行。
void MyUsrType::releaseConnNode(khala::InfoNodePtr& infoNodePtr, khala::Timestamp time) { UsrInfo* usrInfo = boost::any_cast<UsrInfo*>( infoNodePtr->getExtraContext()); if (usrInfo != 0){ //释放设备申请的资源 delete usrInfo; usrInfo = 0; } }
我们通过客户端程序(./example/testClient/HelloKhalaClient3.py)对其进行测试。首先选择UsrType类型进行登录操作。
然后我们添加一个friend,id为100,然后再查询所有friend的id,显示只有100一个id。
我们再为这个用户添加一个friend,id为200,然后再通过getFriends进行查询,这时显示存在100和200两个id了。
最后我们选择退出,并查看日志,看是否我们申请的资源能否随着设备账号的退出而成功释放。通过日志显示,我们这个账号名为moss1的设备申请的UsrInfo资源随着设备生命周期的结束而成功释放了。
通过以上实例,我们实现了MyUsrType类型设备对UsrInfo资源的申请管理和释放。Khala用户可以根据实际业务需求来为不同设备申请和管理相应的设备资源。