In Aeste, we learn something new every day, except for weekends, because we don’t work on weekends :). Dr. Shawn was here for a few days and it was nice to have his guidance and insights on things. The past weeks I have worked on the project, I kept adding in functions, creating widget, in short, expanding ONE big project file. The various storage requests (delete, create, update, etc.) and different WContainerWidgets (board display, project display and info display) were all in one file, needless to say, it would take the next person working on the project a lot time to understand.

Rebuilding the application

It was obvious what I was tasked to do: to build it in a modular structure, so that it can be like Lego pieces. This required me to take apart what was already working, which was quite saddening. However, doing this made me realize what are the better programming habits that should be had.

After much work, the storage backend is now in a completely separate class and file.  To communicate with the main WApplication, I created a few signals to notify completed requests to Google Drive. I like how simple and straightforward it is. In the storage file, I create the signal and its accessor, in the example, I demonstrate a signal for that emits a string:

Wt::Signal<std::string>& onDone(){return onDone_;}

Wt::Signal<std::string> onDone_;

To emit the signal in the storage app:

onDone.emit(someString);

Whereas in my main WApp, where I have created the storage object, I connect the signal  by doing so:

storageObject->onDone().connect(this, &WApp::doThisOnDone);

Communicating from a WResource to WApplication

This was the part where I faced the most difficulty. We can’t emit signals from a WResource and there is not doJavaScript member function available. In my application, I have deployed a WResource which handles requests from other clients. I needed the resource to communicate with the session after a request is received. Reading through Wt documentation, there was two way around this:-

  • Grab the application lock and manipulate the state. I kept getting seg fault while attempting this.
  • Use WServer::post, which executes a given function for the session.

I manage to get WServer::post to work and I think it will be useful for future works. The steps to get it working is as follows:-

  • addResource in ‘int main()’. *Note: never addResource in a WApplication as it will lead to deployment failure when the user redirects.

We need a pointer to the WResource which was set in ‘int main()’ in our WApp. So, a way to do this is to pass the pointer when WApp is created. For example:-

Wt::WApplication *createWApp(const Wt::WEnvironment& e)
{
WApp *wApp= new WApp(e,resourcePointer); //where resourcePointer is Wt::WResource*
return dash;
}

  • In wApp, we now have a reference to the resource. The next step is to pass a function (which we wish to execute in WResource) to the WResource. I followed the Wt example ‘broadcast’ as a guideline.

resourcePointer->connect(boost::bind(&WApp::postFunction));

‘connect’ is simply a WResource member function which constructs and initialize an structure with sessionId and the passed function.

  1. In the WResource…

Wt::WServer::instance()->post(struct.sessionId, struct.function);

That is about it. One problem I still face is passing parameters into the function using boost::bind. Being a boost::bind error, it was too gibberish for me to figure out the source. I worked-around this by executing member functions which returns the data I want from WResource. Something like:

void postFunction(){
std::string getString = resourecePointer->returnString();
}


Metadata storing instead of file storing

Previously, I made a mistake where the application downloads all the project files into appRoot() every time a user signs in. This is a huge waste of requests and incurs valuable storage space. So, instead of storing the actual file, we store the metadata. The trouble was having to edit the metadata every time the projects are modified. I am using boost::regex to search and replace certain parts of the metadata. Throughout my flow, I would need to maintain a certain JSON format, because a small difference might cause a false match on regex.

In the metadata file, I have added a hash key to ensure the integrity of the project file. When the project file is uploaded, the contents are passed into a cryptographic function and saved in the metadata. Again, Wt provides an API for this, which makes it so simple for me. The next time the user downloads the file, the contents will be hashed again and compared. This acts as a safety feature to prevent unwanted files being sent to our server.

 

Categories: Experiential

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.