Add state tracking plumbing
Summary: The plan is to get SonarState to take update events and aggregate them into an object, that can be displayed in the UI so you can see what sonar is currently trying to do, and what if anything is failing. This is pretty rubbish right now, as it just uses a single string to represent state, this is just the initial version I'll iterate on. I also need to pass the SonarState into the SonarWebSocketImpl, since that's where a lot of the heavy lifting is done, but as long as something is logging state updates here, it proves the concept. SonarStateUpdateListener is the interface that will be implemented by android and iOS implementations. These implementations will notify an activity or screen that the state has changed and they should reflect that. Reviewed By: danielbuechele Differential Revision: D9150551 fbshipit-source-id: 8dd585ca503d32e684ff843d66a59a50a420b4c0
This commit is contained in:
committed by
Facebook Github Bot
parent
c07d8c14a4
commit
91e94815b4
@@ -22,6 +22,7 @@
|
|||||||
#include <Sonar/SonarWebSocket.h>
|
#include <Sonar/SonarWebSocket.h>
|
||||||
#include <Sonar/SonarConnection.h>
|
#include <Sonar/SonarConnection.h>
|
||||||
#include <Sonar/SonarResponder.h>
|
#include <Sonar/SonarResponder.h>
|
||||||
|
#include <Sonar/SonarStateUpdateListener.h>
|
||||||
|
|
||||||
using namespace facebook;
|
using namespace facebook;
|
||||||
using namespace facebook::sonar;
|
using namespace facebook::sonar;
|
||||||
@@ -198,6 +199,37 @@ class JSonarPlugin : public jni::JavaClass<JSonarPlugin> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class JSonarStateUpdateListener : public jni::JavaClass<JSonarStateUpdateListener> {
|
||||||
|
public:
|
||||||
|
constexpr static auto kJavaDescriptor = "Lcom/facebook/sonar/core/SonarStateUpdateListener;";
|
||||||
|
|
||||||
|
void onUpdate() {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<void()>("onUpdate");
|
||||||
|
method(self());
|
||||||
|
}
|
||||||
|
void onStepStarted(std::string step) {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<void(std::string)>("onStepStarted");
|
||||||
|
method(self(), step);
|
||||||
|
}
|
||||||
|
void onStepSuccess(std::string step) {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<void(std::string)>("onStepSuccess");
|
||||||
|
method(self(), step);
|
||||||
|
}
|
||||||
|
void onStepFailed(std::string step, std::string errorMessage) {
|
||||||
|
static const auto method = javaClassStatic()->getMethod<void(std::string, std::string)>("onStepFailed");
|
||||||
|
method(self(), step, errorMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class AndroidSonarStateUpdateListener : public SonarStateUpdateListener {
|
||||||
|
public:
|
||||||
|
AndroidSonarStateUpdateListener(jni::alias_ref<JSonarStateUpdateListener> stateListener);
|
||||||
|
void onUpdate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
jni::global_ref<JSonarStateUpdateListener> jStateListener;
|
||||||
|
};
|
||||||
|
|
||||||
class JSonarPluginWrapper : public SonarPlugin {
|
class JSonarPluginWrapper : public SonarPlugin {
|
||||||
public:
|
public:
|
||||||
jni::global_ref<JSonarPlugin> jplugin;
|
jni::global_ref<JSonarPlugin> jplugin;
|
||||||
@@ -229,7 +261,10 @@ class JSonarClient : public jni::HybridClass<JSonarClient> {
|
|||||||
makeNativeMethod("stop", JSonarClient::stop),
|
makeNativeMethod("stop", JSonarClient::stop),
|
||||||
makeNativeMethod("addPlugin", JSonarClient::addPlugin),
|
makeNativeMethod("addPlugin", JSonarClient::addPlugin),
|
||||||
makeNativeMethod("removePlugin", JSonarClient::removePlugin),
|
makeNativeMethod("removePlugin", JSonarClient::removePlugin),
|
||||||
|
makeNativeMethod("subscribeForUpdates", JSonarClient::subscribeForUpdates),
|
||||||
|
makeNativeMethod("unsubscribe", JSonarClient::unsubscribe),
|
||||||
makeNativeMethod("getPlugin", JSonarClient::getPlugin),
|
makeNativeMethod("getPlugin", JSonarClient::getPlugin),
|
||||||
|
makeNativeMethod("getState", JSonarClient::getState),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +291,22 @@ class JSonarClient : public jni::HybridClass<JSonarClient> {
|
|||||||
client->removePlugin(client->getPlugin(plugin->identifier()));
|
client->removePlugin(client->getPlugin(plugin->identifier()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void subscribeForUpdates(jni::alias_ref<JSonarStateUpdateListener> stateListener) {
|
||||||
|
auto client = SonarClient::instance();
|
||||||
|
mStateListener = std::make_shared<AndroidSonarStateUpdateListener>(stateListener);
|
||||||
|
client->setStateListener(mStateListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unsubscribe() {
|
||||||
|
auto client = SonarClient::instance();
|
||||||
|
mStateListener = nullptr;
|
||||||
|
client->setStateListener(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getState() {
|
||||||
|
return SonarClient::instance()->getState();
|
||||||
|
}
|
||||||
|
|
||||||
jni::alias_ref<JSonarPlugin> getPlugin(const std::string& identifier) {
|
jni::alias_ref<JSonarPlugin> getPlugin(const std::string& identifier) {
|
||||||
auto plugin = SonarClient::instance()->getPlugin(identifier);
|
auto plugin = SonarClient::instance()->getPlugin(identifier);
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
@@ -295,6 +346,7 @@ class JSonarClient : public jni::HybridClass<JSonarClient> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend HybridBase;
|
friend HybridBase;
|
||||||
|
std::shared_ptr<SonarStateUpdateListener> mStateListener = nullptr;
|
||||||
|
|
||||||
JSonarClient() {}
|
JSonarClient() {}
|
||||||
};
|
};
|
||||||
@@ -309,3 +361,11 @@ jint JNI_OnLoad(JavaVM* vm, void*) {
|
|||||||
JEventBase::registerNatives();
|
JEventBase::registerNatives();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AndroidSonarStateUpdateListener::AndroidSonarStateUpdateListener(jni::alias_ref<JSonarStateUpdateListener> stateListener) {
|
||||||
|
jStateListener = jni::make_global(stateListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AndroidSonarStateUpdateListener::onUpdate() {
|
||||||
|
jStateListener->onUpdate();
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.facebook.soloader.SoLoader;
|
|||||||
import com.facebook.sonar.BuildConfig;
|
import com.facebook.sonar.BuildConfig;
|
||||||
import com.facebook.sonar.core.SonarClient;
|
import com.facebook.sonar.core.SonarClient;
|
||||||
import com.facebook.sonar.core.SonarPlugin;
|
import com.facebook.sonar.core.SonarPlugin;
|
||||||
|
import com.facebook.sonar.core.SonarStateUpdateListener;
|
||||||
|
|
||||||
@DoNotStrip
|
@DoNotStrip
|
||||||
class SonarClientImpl implements SonarClient {
|
class SonarClientImpl implements SonarClient {
|
||||||
@@ -55,4 +56,13 @@ class SonarClientImpl implements SonarClient {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native void stop();
|
public native void stop();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void subscribeForUpdates(SonarStateUpdateListener stateListener);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native void unsubscribe();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public native String getState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,10 @@ public interface SonarClient {
|
|||||||
void start();
|
void start();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void subscribeForUpdates(SonarStateUpdateListener stateListener);
|
||||||
|
|
||||||
|
void unsubscribe();
|
||||||
|
|
||||||
|
String getState();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.facebook.sonar.core;
|
||||||
|
|
||||||
|
public interface SonarStateUpdateListener {
|
||||||
|
|
||||||
|
void onUpdate();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "SonarClient.h"
|
#include "SonarClient.h"
|
||||||
#include "SonarConnectionImpl.h"
|
#include "SonarConnectionImpl.h"
|
||||||
#include "SonarResponderImpl.h"
|
#include "SonarResponderImpl.h"
|
||||||
|
#include "SonarState.h"
|
||||||
|
#include "SonarStep.h"
|
||||||
#include "SonarWebSocketImpl.h"
|
#include "SonarWebSocketImpl.h"
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
@@ -37,6 +39,12 @@ SonarClient* SonarClient::instance() {
|
|||||||
return kInstance;
|
return kInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SonarClient::setStateListener(
|
||||||
|
std::shared_ptr<SonarStateUpdateListener> stateListener) {
|
||||||
|
SONAR_LOG("Setting state listener");
|
||||||
|
sonarState_->setUpdateListener(stateListener);
|
||||||
|
}
|
||||||
|
|
||||||
void SonarClient::addPlugin(std::shared_ptr<SonarPlugin> plugin) {
|
void SonarClient::addPlugin(std::shared_ptr<SonarPlugin> plugin) {
|
||||||
SONAR_LOG(("SonarClient::addPlugin " + plugin->identifier()).c_str());
|
SONAR_LOG(("SonarClient::addPlugin " + plugin->identifier()).c_str());
|
||||||
|
|
||||||
@@ -198,6 +206,10 @@ void SonarClient::performAndReportError(const std::function<void()>& func) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SonarClient::getState() {
|
||||||
|
return sonarState_->getState();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sonar
|
} // namespace sonar
|
||||||
} // namespace facebook
|
} // namespace facebook
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
#include <Sonar/SonarConnectionImpl.h>
|
#include <Sonar/SonarConnectionImpl.h>
|
||||||
#include <Sonar/SonarInitConfig.h>
|
#include <Sonar/SonarInitConfig.h>
|
||||||
#include <Sonar/SonarPlugin.h>
|
#include <Sonar/SonarPlugin.h>
|
||||||
|
#include <Sonar/SonarState.h>
|
||||||
#include <Sonar/SonarWebSocket.h>
|
#include <Sonar/SonarWebSocket.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include "SonarStep.h"
|
||||||
|
|
||||||
namespace facebook {
|
namespace facebook {
|
||||||
namespace sonar {
|
namespace sonar {
|
||||||
@@ -39,6 +41,7 @@ class SonarClient : public SonarWebSocket::Callbacks {
|
|||||||
*/
|
*/
|
||||||
SonarClient(std::unique_ptr<SonarWebSocket> socket)
|
SonarClient(std::unique_ptr<SonarWebSocket> socket)
|
||||||
: socket_(std::move(socket)) {
|
: socket_(std::move(socket)) {
|
||||||
|
sonarState_ = std::make_unique<SonarState>();
|
||||||
socket_->setCallbacks(this);
|
socket_->setCallbacks(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +65,13 @@ class SonarClient : public SonarWebSocket::Callbacks {
|
|||||||
|
|
||||||
void refreshPlugins();
|
void refreshPlugins();
|
||||||
|
|
||||||
|
void setStateListener(
|
||||||
|
std::shared_ptr<SonarStateUpdateListener> stateListener);
|
||||||
|
|
||||||
std::shared_ptr<SonarPlugin> getPlugin(const std::string& identifier);
|
std::shared_ptr<SonarPlugin> getPlugin(const std::string& identifier);
|
||||||
|
|
||||||
|
std::string getState();
|
||||||
|
|
||||||
template <typename P>
|
template <typename P>
|
||||||
std::shared_ptr<P> getPlugin(const std::string& identifier) {
|
std::shared_ptr<P> getPlugin(const std::string& identifier) {
|
||||||
return std::static_pointer_cast<P>(getPlugin(identifier));
|
return std::static_pointer_cast<P>(getPlugin(identifier));
|
||||||
@@ -78,6 +86,7 @@ class SonarClient : public SonarWebSocket::Callbacks {
|
|||||||
std::map<std::string, std::shared_ptr<SonarPlugin>> plugins_;
|
std::map<std::string, std::shared_ptr<SonarPlugin>> plugins_;
|
||||||
std::map<std::string, std::shared_ptr<SonarConnectionImpl>> connections_;
|
std::map<std::string, std::shared_ptr<SonarConnectionImpl>> connections_;
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
|
std::unique_ptr<SonarState> sonarState_;
|
||||||
|
|
||||||
void performAndReportError(const std::function<void()>& func);
|
void performAndReportError(const std::function<void()>& func);
|
||||||
void disconnect(std::shared_ptr<SonarPlugin> plugin);
|
void disconnect(std::shared_ptr<SonarPlugin> plugin);
|
||||||
|
|||||||
54
xplat/Sonar/SonarState.cpp
Normal file
54
xplat/Sonar/SonarState.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "SonarState.h"
|
||||||
|
#include "SonarStateUpdateListener.h"
|
||||||
|
#include "SonarStep.h"
|
||||||
|
|
||||||
|
/* Class responsible for collecting state updates and combining them into a
|
||||||
|
* view of the current state of the sonar client. */
|
||||||
|
|
||||||
|
SonarState::SonarState() {
|
||||||
|
stateUpdates = "";
|
||||||
|
}
|
||||||
|
void SonarState::setUpdateListener(
|
||||||
|
std::shared_ptr<SonarStateUpdateListener> listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SonarState::started(std::string step) {
|
||||||
|
stateUpdates = stateUpdates + "[Started] " + step + "\n";
|
||||||
|
if (mListener) {
|
||||||
|
mListener->onUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SonarState::success(std::string step) {
|
||||||
|
stateUpdates = stateUpdates + "[Success] " + step + "\n";
|
||||||
|
if (mListener) {
|
||||||
|
mListener->onUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SonarState::failed(std::string step, std::string errorMessage) {
|
||||||
|
stateUpdates = stateUpdates + "[Failed] " + step + "\n";
|
||||||
|
if (mListener) {
|
||||||
|
mListener->onUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Currently returns string, but should really provide a better
|
||||||
|
// representation of the current state so the UI can show it in a more intuitive
|
||||||
|
// way
|
||||||
|
std::string SonarState::getState() {
|
||||||
|
return stateUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SonarStep> SonarState::start(std::string step_name) {
|
||||||
|
started(step_name);
|
||||||
|
return std::make_shared<SonarStep>(step_name, this);
|
||||||
|
}
|
||||||
37
xplat/Sonar/SonarState.h
Normal file
37
xplat/Sonar/SonarState.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SonarStep;
|
||||||
|
class SonarStateUpdateListener;
|
||||||
|
|
||||||
|
class SonarState {
|
||||||
|
friend SonarStep;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SonarState();
|
||||||
|
void setUpdateListener(std::shared_ptr<SonarStateUpdateListener>);
|
||||||
|
std::string getState();
|
||||||
|
|
||||||
|
/* To record a state update, call start() with the name of the step to get a
|
||||||
|
SonarStep object. Call complete on this to register it successful,
|
||||||
|
the absense of the completion call when it is destructed will register as a
|
||||||
|
step failure. */
|
||||||
|
std::shared_ptr<SonarStep> start(std::string step);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void success(std::string);
|
||||||
|
void failed(std::string, std::string);
|
||||||
|
void started(std::string);
|
||||||
|
std::shared_ptr<SonarStateUpdateListener> mListener = nullptr;
|
||||||
|
std::string stateUpdates;
|
||||||
|
};
|
||||||
14
xplat/Sonar/SonarStateUpdateListener.h
Normal file
14
xplat/Sonar/SonarStateUpdateListener.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class SonarStateUpdateListener {
|
||||||
|
public:
|
||||||
|
virtual void onUpdate() = 0;
|
||||||
|
};
|
||||||
25
xplat/Sonar/SonarStep.cpp
Normal file
25
xplat/Sonar/SonarStep.cpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "SonarStep.h"
|
||||||
|
#include "SonarState.h"
|
||||||
|
|
||||||
|
void SonarStep::complete() {
|
||||||
|
isCompleted = true;
|
||||||
|
state->success(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
SonarStep::SonarStep(std::string step, SonarState* s) {
|
||||||
|
state = s;
|
||||||
|
name = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
SonarStep::~SonarStep() {
|
||||||
|
if (!isCompleted) {
|
||||||
|
state->failed(name, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
25
xplat/Sonar/SonarStep.h
Normal file
25
xplat/Sonar/SonarStep.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the LICENSE
|
||||||
|
* file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class SonarState;
|
||||||
|
|
||||||
|
class SonarStep {
|
||||||
|
public:
|
||||||
|
void complete();
|
||||||
|
SonarStep(std::string name, SonarState* state);
|
||||||
|
~SonarStep();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string name;
|
||||||
|
bool isCompleted = false;
|
||||||
|
SonarState* state;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user