How to create a maintenance hook? - pimcore

I´m trying to make a hook into the maintenance procedure.
I have tried the following in my Plugin.php:
<?php
namespace MyPlugin;
class Plugin extends PluginLib\AbstractPlugin implements PluginLib\PluginInterface {
public function init() {
// Make an maintenance hook
\Pimcore::getEventManager()->attach("system.maintenance", array($this, "maintenance"));
}
...
public function maintenance()
{
$logger = new \Pimcore\Log\Log();
$logger->setComponent("pimcore logger");
$logger->addWriter(new \Zend_Log_Writer_Stream('/var/www/site/website/var/log/debug.log'));
$logger->info('Running maintenance ...');
}
}
I don´t see my message in the logs.. but I have the maintenance setuped in cron, I can see the maintenance are running in the logs, but not my message.
Also the plugin is installed and activated.
What I understand from the Event Manager this should be the way to do it. What could I be doing wrong?
Thanks /J

Related

ServiceStack with MiniProfiler for .Net 6

I was attempting to add Profiling into ServiceStack 6 with .Net 6 and using the .Net Framework MiniProfiler Plugin code as a starting point.
I noticed that ServiceStack still has Profiler.Current.Step("Step Name") in the Handlers, AutoQueryFeature and others.
What is currently causing me some stress is the following:
In ServiceStackHandlerBase.GetResponseAsync(IRequest httpReq, object request) the Async Task is not awaited. This causes the step to be disposed of the when it reaches the first async method it must await, causing all the subsequent nested steps to not be children. Is there something simple I'm missing here or is this just a bug in a seldom used feature?
In SqlServerOrmLiteDialectProvider most of the async methods make use of an Unwrap function that drills down to the SqlConnection or SqlCommand this causes an issue when attempting to wrap a command to enable profiling as it ignores the override methods in the wrapper in favour of the IHasDbCommand.DbCommand nested within. Not using IHasDbCommand on the wrapping command makes it attempt to use wrapping command but hits a snag because of the forced cast to SqlCommand. Is there an easy way to combat this issue, or do I have to extend each OrmliteDialectProvider I wish to use that has this issue to take into account the wrapping command if it is present?
Any input would be appreciated.
Thanks.
Extra Information Point 1
Below is the code from ServiceStackHandlerBase that appears (to me) to be a bug?
public virtual Task<object> GetResponseAsync(IRequest httpReq, object request)
{
using (Profiler.Current.Step("Execute " + GetType().Name + " Service"))
{
return appHost.ServiceController.ExecuteAsync(request, httpReq);
}
}
I made a small example that shows what I am looking at:
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task<int> Main(string[] args)
{
Console.WriteLine("App Start.");
await GetResponseAsync();
Console.WriteLine("App End.");
return 0;
}
// Async method with a using and non-awaited task.
private static Task GetResponseAsync()
{
using(new Test())
{
return AdditionAsync();
}
}
// Placeholder async method.
private static async Task AdditionAsync()
{
Console.WriteLine("Async Task Started.");
await Task.Delay(2000);
Console.WriteLine("Async Task Complete.");
}
}
public class Test : IDisposable
{
public Test()
{
Console.WriteLine("Disposable instance created.");
}
public void Dispose()
{
Console.WriteLine("Disposable instance disposed.");
}
}
My Desired Result:
App Start.
Disposable instance created.
Async Task Started.
Async Task Complete.
Disposable instance disposed.
App End.
My Actual Result:
App Start.
Disposable instance created.
Async Task Started.
Disposable instance disposed.
Async Task Complete.
App End.
This to me shows that even though the task is awaited at a later point in the code, the using has already disposed of the contained object.
Mini Profiler was coupled to System.Web so isn't supported in ServiceStack .NET6.
To view the generated SQL you can use a BeforeExecFilter to inspect the IDbCommand before it's executed.
This is what PrintSql() uses to write all generated SQL to the console:
OrmLiteUtils.PrintSql();
Note: when you return a non-awaited task it just means it doesn't get awaited at that point, it still gets executed when the return task is eventually awaited.
To avoid the explicit casting you should be able to override a SQL Server Dialect Provider where you'll be able to replace the existing implementation with your own.

Cocos2d-x Multithreading sceanrio crashes the game

my scenario is simple:i made a game using cocos2d-x and i want to download images (FB and Google play) for multi player users and show them once the download is done as texture for a button.
in ideal world, things work as expected.
things get tricky when those buttons got deleted before the download is done.
so the callback function is in weird state and then i get signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
and the app crashes
This is how i implmented it
I have a Layout class called PlayerIcon. the cpp looks like this
void PlayerIcon::setPlayer(string userName, string displayName, string avatarUrl){
try {
//some code here
downloadAvatar(_userName, _avatarUrl);
//some code here
}
catch(... ){
}
}
void PlayerIcon::downloadAvatar(std::string _avatarFilePath,std::string url) {
if(!isFileExist(_avatarFilePath)) {
try {
auto downloader = new Downloader();
downloader->onFileTaskSuccess=CC_CALLBACK_1(PlayerIcon::on_download_success,this);
downloader->onTaskError=[&](const network::DownloadTask& task,int errorCode,
int errorCodeInternal,
const std::string& errorStr){
log("error while saving image");
};
downloader->createDownloadFileTask(url,_avatarFilePath,_avatarFilePath);
}
catch (exception e)
{
log("error while saving image: test");
}
} else {
//set texture for button
}
}
void PlayerIcon::on_download_success(const network::DownloadTask& task){
_isDownloading = false;
Director::getInstance()->getScheduler()-> performFunctionInCocosThread(CC_CALLBACK_0(PlayerIcon::reload_avatar,this));
}
void PlayerIcon::reload_avatar(){
try {
// setting texture in UI thread
}
catch (...) {
log("error updating avatar");
}
}
As i said, things works fine until PlayerIcon is deleted before the download is done.
i dont know what happens when the call back of the download task point to a method of un object that s deleted (or flagged for deletion).
i looked in the downloader implementation and it doesn't provide any cancellation mechanism
and i'm not sure how to handle this
Also, is it normal to have 10% crash rate on google console for a cocos2dx game
any help is really appreciated
Do you delete de Downloader in de destructor of the PlayerIcon?
there is a destroy in the apple implementation witch is trigered by the destructor.
-(void)doDestroy
{
// cancel all download task
NSEnumerator * enumeratorKey = [self.taskDict keyEnumerator];
for (NSURLSessionDownloadTask *task in enumeratorKey)
{
....
DownloaderApple::~DownloaderApple()
{
DeclareDownloaderImplVar;
[impl doDestroy];
DLLOG("Destruct DownloaderApple %p", this);
}
In the demo code of cocos2d-x: DownloaderTest.cpp they use:
std::unique_ptr<network::Downloader> downloader;
downloader.reset(new cocos2d::network::Downloader());
instead of:
auto downloader = new Downloader();
It looks like you are building this network code as part of your scene tree. If you do a replaceScene/popScene...() call, while the async network software is running in the background, this will cause the callback to disappear (the scene will be deleted from the scene-stack) and you will get a SEGFAULT from this.
If this is the way you've coded it, then you might want to extract the network code to a global object (singleton) where you queue the requests and then grab them off the internet saving the results in the global-object's output queue (or their name and location) and then let the scene code check to see if the avatar has been received yet by inquiring on the global-object and loading the avatar sprite at this point.
Note, this may be an intermittent problem which depends on the speed of your machine and the network so it may not be triggered consistently.
Another solution ...
Or you could just set your function pointers to nullptr in your PlayerIcon::~PlayerIcon() (destructor):
downloader->setOnFileTaskSuccess(nullptr);
downloader->setOnTaskProgress(nullptr);
Then there will be no attempt to call your callback functions and the SEGFAULT will be avoided (Hopefully).

Log4Net how to log

I am new with log4net and am wondering how to properly be able to log. I have seen examples of people doing Logs.Enter, Logs.Exit. It properly logs and helps users when testing/debugging. Examples of how to define is greatly appreciated
You define a log4net log like so:
private static log4net.ILog log = log4net.LogManager.GetLogger(ConfigurationManager.AppSettings["LogName"]);
I defined it so that it is defined in app config. Afterwards, I define methods to determine the type of log i.e. Error, Info, Enter, Exit etc.
Enter/Exit method example:
[Conditional("ENTEREXIT")]
public static void Enter()
{
_log.Info(GetMethodName() + ": In");
}
[Conditional("ENTEREXIT")]
public static void Exit()
{
_log.Info(GetMethodName() + ": Out");
}
Save this in a separate class called Logs.cs
Then, whenever you want to log, you simple do Logs.Enter and then stop logging with Logs.Exit. You can do Logs.Info or Logs.Error without the Enter/Exit Logs.

OWIN self-host IAppBuilder map if part of Windows group

I have following setup:
Self-host OWIN server (Windows Service). In the OWIN startup class, I configured httpListener to only allow Windows Authentication. This works.
...
HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
this.ConfigureSomeApp();
...
private void ConfigureSomeApp()
{
app.Map("/someapp", someApp => { //appconfig here, ommitted for brevity };
}
The thing I'm trying to achieve is to ONLY map "someapp" based on some conditions regarding the current user (i.e. if the user is a member of a specified Windows group).
I cannot seem to find how to do this. Is this possible ? Something like:
private void ConfigureSomeApp()
{
if(currentuser is in windowsgroup) //pseudo example condition I want to achieve
app.Map("/someapp", someApp => { //appconfig here, ommitted for brevity };
}
If not possible here in the startup class, what are your other suggestions on how to achieve this ?
For info: I do not control the "someapp" implementation, it comes from a NuGet package
This is not the correct way to do this
{
if(currentuser is in windowsgroup) //pseudo example condition I want to achieve
app.Map("/someapp", someApp => { //appconfig here, ommitted for brevity };
}
because ConfigureSomeApp method is in startup and startup only run once, therefor your if statement won't run for every request.
You have to use app.MapWhen
app.MapWhen(context =>
{
// check the logic for user
//context.Authentication.User
return true; // return true if you want to map for this request
}, someapp => /*config someapp*/);

Porting from gridgain to ignite - what the ignite equivalents for these gridgain methods

In porting our code base from gridgain to ignite, I've found similar / renamed methods for most of the ignite methods. There are a few that I need to clarify though.
What is the ignite equivalent for
//Listener for asynchronous local node grid events. You can subscribe for local node grid event notifications via {#link GridEventStorageManager#addLocalEventListener
public interface GridLocalEventListener extends EventListener {}
What is the recommended way to invoke a compute future. See picture for compile failures.
Apart from that, it looks like future.listenAsync() should be future.listen()
final ProcessingTaskAdapter taskAdapter = new ProcessingTaskAdapter(task, manager, node);
ComputeTaskFuture<ProcessingJob> future = grid.cluster()
.forPredicate(this) //===> what should this be
.compute().execute(taskAdapter, job);
future.listen(new IgniteInClosure<IgniteFuture<ProcessingJob>>() {
#Override
public void apply(IgniteFuture<ProcessingJob> future) {
try {
// Need this to extract the remote exception, if one occurred
future.get();
} catch (IgniteException e) {
manager.fail(e.getCause() != null ? e.getCause() : e);
} finally {
manager.finishJob(job);
jobDistributor.distribute(taskAdapter.getSelectedNode());
}
}
There is no special class anymore, you simply use IgnitePredicate as a listener. Refer to [1] for details.
Refer to [2] for information about async support. Also note that projections were replaced with cluster groups [3] (one of your compile errors is because of that). And you're correct, listenAsync was renamed to listen.
[1] https://apacheignite.readme.io/docs/events
[2] https://apacheignite.readme.io/docs/async-support
[3] https://apacheignite.readme.io/docs/cluster-groups

Resources