1/*
2 * Copyright 2021-2023, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#include "IncrementViewCounterProcess.h"
6
7#include <Catalog.h>
8
9#include "Logger.h"
10#include "ServerHelper.h"
11#include "WebAppInterface.h"
12
13
14#define ATTEMPTS						3
15#define SPIN_BETWEEN_ATTEMPTS_DELAY_MI	5 * 1000 * 1000
16	// 5 seconds
17
18#undef B_TRANSLATION_CONTEXT
19#define B_TRANSLATION_CONTEXT "IncrementViewCounterProcess"
20
21
22IncrementViewCounterProcess::IncrementViewCounterProcess(
23	Model* model, const PackageInfoRef& package)
24	:
25	fPackage(package),
26	fModel(model)
27{
28	fDescription = BString(B_TRANSLATE("Recording view of \"%PackageName%\""))
29		.ReplaceAll("%PackageName%", fPackage->Name());
30}
31
32
33IncrementViewCounterProcess::~IncrementViewCounterProcess()
34{
35}
36
37
38const char*
39IncrementViewCounterProcess::Name() const
40{
41	return "IncrementViewCounterProcess";
42}
43
44
45const char*
46IncrementViewCounterProcess::Description() const
47{
48	return fDescription.String();
49}
50
51
52status_t
53IncrementViewCounterProcess::RunInternal()
54{
55	if (!ServerHelper::IsNetworkAvailable()) {
56		HDINFO("no network so will not increment view counter");
57		return B_OK;
58	}
59
60	if (!fPackage.IsSet()) {
61		HDERROR("the package is not present to increment the view counter");
62		return B_ERROR;
63	}
64
65	DepotInfoRef depot = fModel->DepotForName(fPackage->DepotName());
66
67	if (!depot.IsSet()) {
68		HDERROR("the package's depot is not present to increment the view "
69			"counter");
70		return B_ERROR;
71	}
72
73	if (depot->WebAppRepositorySourceCode().IsEmpty()) {
74		HDERROR("cannot increment view counter because depot has no web app "
75			"repository source code");
76		return B_BAD_DATA;
77	}
78
79	int32 attempts = ATTEMPTS;
80	status_t result = B_OK;
81
82	while (attempts > 0 && !WasStopped()) {
83		BMessage resultEnvelope;
84		WebAppInterface* webAppInterface = fModel->GetWebAppInterface();
85		result = webAppInterface->IncrementViewCounter(fPackage, depot, resultEnvelope);
86
87		if (result == B_OK) {
88			int32 errorCode = WebAppInterface::ErrorCodeFromResponse(resultEnvelope);
89			switch (errorCode) {
90				case ERROR_CODE_NONE:
91					HDINFO("did increment the view counter for [%s]",
92						fPackage->Name().String());
93					return result;
94				case ERROR_CODE_OBJECTNOTFOUND:
95					HDINFO("server was not able to find the package [%s]",
96						fPackage->Name().String());
97					return B_NAME_NOT_FOUND;
98				default:
99					HDERROR("a problem has arisen incrementing the view "
100					"counter for pkg [%s] w/ error code %" B_PRId32,
101					fPackage->Name().String(), errorCode);
102					result = B_ERROR;
103					break;
104			}
105		} else
106			HDERROR("an error has arisen incrementing the view counter");
107
108		attempts--;
109		_SpinBetweenAttempts();
110	}
111
112	return result;
113}
114
115
116void
117IncrementViewCounterProcess::_SpinBetweenAttempts()
118{
119	useconds_t miniSpinDelays = SPIN_BETWEEN_ATTEMPTS_DELAY_MI / 10;
120	for (int32 i = 0; i < 10 && !WasStopped(); i++)
121		usleep(miniSpinDelays);
122}
123
124