Skip to content

Commit 31db569

Browse files
committedDec 30, 2021
Use CURL multi handle, and process API calls asynchronously
1 parent 98f21c1 commit 31db569

8 files changed

+130
-32
lines changed
 

‎config.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<?php
22
define('CLIENT_ID', 'ju16a6m81mhid5ue1z3v2g0uh');
3-
define('ENABLE_LOG', false);
4-
define('LOG_FILE_PATH', __DIR__.'/log/supermetricsClient2.log');
3+
define('ENABLE_LOG', true);
4+
define('LOG_FILE_PATH', __DIR__ . '/log/supermetricsApi.log');

‎log/SupermetricsClient.log

Whitespace-only changes.

‎src/lib/Aggregator.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ private function getMonthlyStats(): array
8181
foreach ($this->monthly as $month => $val) {
8282
$out['monthly_stats'][] = [
8383
'month' => $month,
84-
'average_character_length_of_post' => $val['total_chars'] / $val['post_count'],
84+
'average_character_length_of_post' => round(($val['total_chars'] / $val['post_count']),2),
8585
'longest_post' => $val['longest_post'],
86-
'average_number_of_posts_per_user' => $val['post_count'] / count($val['user_ids']),
86+
'average_number_of_posts_per_user' => round(($val['post_count']/count($val['user_ids'])),2),
8787
];
8888
}
8989
return $out;

‎src/lib/SupermetricsApi.php

+15-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/**
88
* Supermetrics API handler
9+
* Create new methods for new API endpoints
910
*/
1011
class SupermetricsApi extends SupermetricsClient
1112
{
@@ -16,11 +17,23 @@ public function __construct(string $email, string $name, $clientId)
1617
}
1718

1819
/**
19-
* Fetch posts form the API
20+
* Fetch one page form the API
2021
* @param int pageNumber
2122
*/
2223
public function fetchPost(int $pageNumber): object
2324
{
24-
return $this->callAPI('assignment/posts', ['page' => $pageNumber]);
25+
return $this->callApi('assignment/posts', ['page' => $pageNumber]);
26+
}
27+
28+
/**
29+
* Fetch number of pages from the API
30+
* @param int numberOfPages
31+
*/
32+
public function fetchPosts(int $numberOfPages): array
33+
{
34+
for ($i = 1; $i <= $numberOfPages; $i++) {
35+
$this->setupApiCall('assignment/posts', ['page' => $i]);
36+
}
37+
return $this->executeMultiRequest();
2538
}
2639
}

‎src/lib/SupermetricsClient.php

+93-14
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace supermetrics\lib;
44

5+
use DateTime;
56
use Exception;
67
use InvalidArgumentException;
78
use supermetrics\exception\InvalidTokenException;
@@ -40,6 +41,10 @@ class SupermetricsClient
4041
* Token registered with the API
4142
*/
4243
private $token;
44+
/**
45+
* Curl handlers
46+
*/
47+
private $ch;
4348

4449
public function __construct(string $email, string $name, $clientId)
4550
{
@@ -60,8 +65,8 @@ public function enableLog($log_file_path = null)
6065
}
6166

6267
/**
63-
* This function will handle all API calls
64-
* If postData is not null, consider this as a post request. otherwise, its a get request
68+
* This function will handle single API request
69+
* If postData is not null, consider this as a POST request. otherwise, its a GET request
6570
*/
6671
private function sendRequest(string $requestPath, array $params = [], array $postData = []): object
6772
{
@@ -75,16 +80,12 @@ private function sendRequest(string $requestPath, array $params = [], array $pos
7580
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
7681
}
7782
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
78-
if ($this->isLog) {
79-
$this->log(self::API_BASE_URL . $requestPath);
80-
if (!empty($postData)) {
81-
$this->log('Post Data : ' . json_encode($postData));
82-
}
83+
$this->log(self::API_BASE_URL . $requestPath);
84+
if (!empty($postData)) {
85+
$this->log('Post Data : ' . json_encode($postData));
8386
}
8487
$result = curl_exec($ch);
85-
if ($this->isLog) {
86-
$this->log('Response : ' . $result);
87-
}
88+
$this->log('Response : ' . $result);
8889

8990
if (empty($result)) {
9091
throw new Exception('No response from the API');
@@ -96,6 +97,68 @@ private function sendRequest(string $requestPath, array $params = [], array $pos
9697
return $response;
9798
}
9899

100+
/**
101+
* This function will handle setup CURL for multipal API calls simultaneously
102+
* If postData is not null, consider this as a post request. otherwise, its a get request
103+
*/
104+
private function setMultiRequest(string $requestPath, array $params = [], array $postData = []): void
105+
{
106+
$ch = curl_init();
107+
if (!empty($params)) {
108+
$requestPath .= '?' . http_build_query($params);
109+
}
110+
curl_setopt($ch, CURLOPT_URL, self::API_BASE_URL . $requestPath);
111+
if (!empty($postData)) {
112+
curl_setopt($ch, CURLOPT_POST, 1);
113+
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
114+
}
115+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
116+
$this->log(self::API_BASE_URL . $requestPath);
117+
if (!empty($postData)) {
118+
$this->log('Post Data : ' . json_encode($postData));
119+
}
120+
$this->ch[] = $ch;
121+
}
122+
123+
protected function executeMultiRequest(): array
124+
{
125+
$retVal = [];
126+
$mh = curl_multi_init();
127+
128+
foreach ($this->ch as $ch) {
129+
curl_multi_add_handle($mh, $ch);
130+
}
131+
$active = null;
132+
//execute the handles
133+
do {
134+
$mrc = curl_multi_exec($mh, $active);
135+
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
136+
137+
while ($active && $mrc == CURLM_OK) {
138+
if (curl_multi_select($mh) != -1) {
139+
do {
140+
$mrc = curl_multi_exec($mh, $active);
141+
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
142+
}
143+
}
144+
foreach ($this->ch as $ch) {
145+
$result = curl_multi_getcontent($ch); // get the content
146+
curl_multi_remove_handle($mh, $ch);
147+
148+
$this->log('Response : ' . $result);
149+
150+
if (empty($result)) {
151+
throw new Exception('No response from the API');
152+
}
153+
$response = json_decode($result);
154+
if (!empty($response->error) && $response->error->message == 'Invalid SL Token') {
155+
throw new InvalidTokenException('Expired or Invalid SL Token');
156+
}
157+
$retVal[] = $response;
158+
}
159+
return $retVal;
160+
}
161+
99162
/**
100163
* Get new token request
101164
*/
@@ -113,10 +176,9 @@ private function refreshToken(): void
113176
}
114177

115178
/**
116-
* Setup curl options and call the API
117-
* If postData is not null, consider this as a post request. otherwise, its a get request
179+
* Single API call
118180
*/
119-
protected function callAPI(string $requestPath, array $params = [], array $postData = []): object
181+
protected function callApi(string $requestPath, array $params = [], array $postData = []): object
120182
{
121183
if ($this->token === null) {
122184
$this->refreshToken();
@@ -135,12 +197,29 @@ protected function callAPI(string $requestPath, array $params = [], array $postD
135197
return $retVal;
136198
}
137199

200+
/**
201+
* Setup curl options for multipal API calls
202+
* If postData is not null, consider this as a POST request. otherwise, its a GET request
203+
*/
204+
protected function setupApiCall(string $requestPath, array $params = [], array $postData = []): void
205+
{
206+
if ($this->token === null) {
207+
$this->refreshToken();
208+
}
209+
$params['sl_token'] = $this->token;
210+
211+
$this->setMultiRequest($requestPath, $params, $postData);
212+
}
213+
138214
/**
139215
* Write logfile
140216
*/
141217
private function log(string $data): void
142218
{
143-
file_put_contents($this->logFile, date("Y-m-d H:i:s - ") . $data . "\n", FILE_APPEND);
219+
if ($this->isLog) {
220+
$now = DateTime::createFromFormat('U.u', microtime(true));
221+
file_put_contents($this->logFile, $now->format("Y-m-d H:i:s.v ") . $data . "\n", FILE_APPEND);
222+
}
144223
}
145224

146225
}

‎src/services/SupermetricsService.php

+7-8
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ class SupermetricsService
1313
private $supermetricsApi;
1414
private $aggregator;
1515

16-
public function __construct(string $email, string $name, string $clientId)
16+
public function __construct(string $email, string $name, string $clientId, $enableLog = false, $log_file_path = null)
1717
{
1818
$this->supermetricsApi = new SupermetricsApi($email, $name, $clientId);
1919
$this->aggregator = new Aggregator();
20-
if (ENABLE_LOG) {
21-
$this->supermetricsApi->enableLog(LOG_FILE_PATH);
20+
if ($enableLog) {
21+
$this->supermetricsApi->enableLog($log_file_path);
2222
}
2323
}
2424

@@ -29,11 +29,10 @@ public function __construct(string $email, string $name, string $clientId)
2929
*/
3030
public function getWeeklyMonthlySummary(int $numPages): array
3131
{
32-
for ($i = 1; $i <= $numPages; $i++) {
33-
$response = $this->supermetricsApi->fetchPost($i);
34-
35-
if (!empty($response->data->posts)) {
36-
foreach ($response->data->posts as $post) {
32+
$results = $this->supermetricsApi->fetchPosts($numPages);
33+
foreach ($results as $res) {
34+
if (!empty($res->data->posts)) {
35+
foreach ($res->data->posts as $post) {
3736
$this->aggregator->setData($post);
3837
}
3938
}

‎summary.php

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
33

44
use supermetrics\services\SupermetricsService;
55

6-
$email = 'sampathperera@hotmail.com';
6+
$email = 'SampathPerera@hotmail.com';
77
$name = 'Sampath';
88
$numPages = 10;
99

10-
$supermetricsService = new SupermetricsService($email, $name, CLIENT_ID);
10+
$input = readline('Enter your email: (Default: SampathPerera@hotmail.com) ');
11+
$email = empty($input) ? $email : $input;
12+
$input = readline('Enter your name: (Default: Sampath) ');
13+
$name = empty($input) ? $name : $input;
14+
$input = (int) readline('Number of pages fetch form the API: (Default: 10) ');
15+
$numPages = empty($input) ? $numPages : $input;
16+
17+
$supermetricsService = new SupermetricsService($email, $name, CLIENT_ID, ENABLE_LOG, LOG_FILE_PATH);
1118

1219
$summary = $supermetricsService->getWeeklyMonthlySummary($numPages);
1320

14-
echo json_encode($summary);
21+
echo json_encode($summary);

‎summary_report.json

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.