Skip to content

Commit

Permalink
address feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
Molly Lloyd committed Oct 17, 2018
1 parent 6e09979 commit 997aec6
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 73 deletions.
140 changes: 74 additions & 66 deletions src/util/mapbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,28 +133,40 @@ function formatUrl(obj: UrlObject): string {
return `${obj.protocol}://${obj.authority}${obj.path}${params}`;
}

type TelemetryEventType = 'appUserTurnstile' | 'map.load';

class TelemetryEvent {
eventData: { anonId: ?string, lastSuccess: ?number, accessToken: ?string};
eventData: { lastSuccess: ?number, accessToken: ?string};
anonId: ?string;
queue: Array<any>;
type: TelemetryEventType;
pendingRequest: ?Cancelable;

constructor() {
this.eventData = { anonId: null, lastSuccess: null, accessToken: config.ACCESS_TOKEN};
constructor(type: TelemetryEventType) {
this.type = type;
this.anonId = null;
this.eventData = {lastSuccess: null, accessToken: config.ACCESS_TOKEN};
this.queue = [];
this.pendingRequest = null;
}

fetchEventData() {
const isLocalStorageAvailable = storageAvailable('localStorage');
const storageKey = `${telemEventKey}:${config.ACCESS_TOKEN || ''}`;
const uuidKey = `${telemEventKey}.uuid:${config.ACCESS_TOKEN || ''}`;

if (isLocalStorageAvailable) {
//Retrieve cached data
try {
const data = window.localStorage.getItem(storageKey);
if (data) {
this.eventData = JSON.parse(data);
if (this.type === "appUserTurnstile") {
const data = window.localStorage.getItem(storageKey);
if (data) {
this.eventData = JSON.parse(data);
}
}

const uuid = window.localStorage.getItem(uuidKey);
if (uuid) this.anonId = uuid;
} catch (e) {
warnOnce('Unable to read from LocalStorage');
}
Expand All @@ -164,10 +176,13 @@ class TelemetryEvent {
saveEventData() {
const isLocalStorageAvailable = storageAvailable('localStorage');
const storageKey = `${telemEventKey}:${config.ACCESS_TOKEN || ''}`;

const uuidKey = `${telemEventKey}.uuid:${config.ACCESS_TOKEN || ''}`;
if (isLocalStorageAvailable) {
try {
window.localStorage.setItem(storageKey, JSON.stringify(this.eventData));
window.localStorage.setItem(uuidKey, this.anonId);
if (this.type === "appUserTurnstile") {
window.localStorage.setItem(storageKey, JSON.stringify(this.eventData));
}
} catch (e) {
warnOnce('Unable to write to LocalStorage');
}
Expand All @@ -177,20 +192,48 @@ class TelemetryEvent {

processRequests() {}

queueRequest(date: number | {id: number, timestamp: number}) {
this.queue.push(date);
postEvent(timestamp: number, callback: (err: ?Error) => void) {
const eventsUrlObject: UrlObject = parseUrl(config.EVENTS_URL);
eventsUrlObject.params.push(`access_token=${config.ACCESS_TOKEN || ''}`);
const payload: Object = {
event: this.type,
created: new Date(timestamp).toISOString(),
sdkIdentifier: 'mapbox-gl-js',
sdkVersion: version,
userId: this.anonId
};

if (this.type === "appUserTurnstile") {
payload['enabled.telemetry'] = false;
}

const request: RequestParameters = {
url: formatUrl(eventsUrlObject),
headers: {
'Content-Type': 'text/plain' //Skip the pre-flight OPTIONS request
},
body: JSON.stringify([payload])
};

this.pendingRequest = postData(request, (error) => {
this.pendingRequest = null;
callback(error);
this.saveEventData();
this.processRequests();
});
}

queueRequest(event: number | {id: number, timestamp: number}) {
this.queue.push(event);
this.processRequests();
}
}

export class MapLoadEvent extends TelemetryEvent {
eventData: { anonId: ?string, lastSuccess: ?number, accessToken: ?string};
queue: Array<{ id: number, timestamp: number}>;
pendingRequest: ?Cancelable;
+success: {[number]: boolean};

constructor() {
super();
super('map.load');
this.success = {};
}

Expand All @@ -211,43 +254,27 @@ export class MapLoadEvent extends TelemetryEvent {
// Only one load event should fire per map
if (id && this.success[id]) return;

if (!this.eventData.anonId) {
if (!this.anonId) {
this.fetchEventData();
}

if (!validateUuid(this.eventData.anonId)) {
this.eventData.anonId = uuid();
if (!validateUuid(this.anonId)) {
this.anonId = uuid();
}

const eventsUrlObject: UrlObject = parseUrl(config.EVENTS_URL);
eventsUrlObject.params.push(`access_token=${config.ACCESS_TOKEN || ''}`);
const request: RequestParameters = {
url: formatUrl(eventsUrlObject),
headers: {
'Content-Type': 'text/plain' //Skip the pre-flight OPTIONS request
},
body: JSON.stringify([{
event: 'map.load',
created: new Date(timestamp).toISOString(),
sdkIdentifier: 'mapbox-gl-js',
sdkVersion: version,
userId: this.eventData.anonId
}])
};

this.pendingRequest = postData(request, (error) => {
this.pendingRequest = null;
if (!error) {
this.postEvent(timestamp, (err) => {
if (!err) {
if (id) this.success[id] = true;
this.saveEventData();
this.processRequests();
}
});
}
}


export class TurnstileEvent extends TelemetryEvent {
constructor() {
super('appUserTurnstile');
}

postTurnstileEvent(tileUrls: Array<string>) {
//Enabled only when Mapbox Access Token is set and a source uses
Expand All @@ -268,56 +295,37 @@ export class TurnstileEvent extends TelemetryEvent {
let dueForEvent = this.eventData.accessToken ? (this.eventData.accessToken !== config.ACCESS_TOKEN) : false;
//Reset event data cache if the access token changed.
if (dueForEvent) {
this.eventData.anonId = this.eventData.lastSuccess = null;
this.anonId = this.eventData.lastSuccess = null;
}
if (!this.eventData.anonId || !this.eventData.lastSuccess) {
if (!this.anonId || !this.eventData.lastSuccess) {
//Retrieve cached data
this.fetchEventData();
}

if (!validateUuid(this.eventData.anonId)) {
this.eventData.anonId = uuid();
if (!validateUuid(this.anonId)) {
this.anonId = uuid();
dueForEvent = true;
}
const nextUpdate = this.queue.shift();

const nextUpdate = this.queue.shift();
// Record turnstile event once per calendar day.
if (this.eventData.lastSuccess) {
const lastUpdate = new Date(this.eventData.lastSuccess);
const nextDate = new Date(nextUpdate);
const daysElapsed = (nextUpdate - this.eventData.lastSuccess) / (24 * 60 * 60 * 1000);
dueForEvent = dueForEvent || daysElapsed >= 1 || daysElapsed < -1 || lastUpdate.getDate() !== nextDate.getDate();
} else {
dueForEvent = true;
}

if (!dueForEvent) {
return this.processRequests();
}

const eventsUrlObject: UrlObject = parseUrl(config.EVENTS_URL);
eventsUrlObject.params.push(`access_token=${config.ACCESS_TOKEN || ''}`);

const request: RequestParameters = {
url: formatUrl(eventsUrlObject),
headers: {
'Content-Type': 'text/plain' // Skip the pre-flight OPTIONS request
},
body: JSON.stringify([{
event: 'appUserTurnstile',
created: (new Date(nextUpdate)).toISOString(),
sdkIdentifier: 'mapbox-gl-js',
sdkVersion: version,
'enabled.telemetry': false,
userId: this.eventData.anonId
}])
};

this.pendingRequest = postData(request, (error: ?Error) => {
this.pendingRequest = null;
if (!error) {
this.postEvent(nextUpdate, (err)=> {
if (!err) {
this.eventData.lastSuccess = nextUpdate;
this.eventData.accessToken = config.ACCESS_TOKEN;
this.saveEventData();
this.processRequests();
}
});
}
Expand Down
13 changes: 6 additions & 7 deletions test/unit/util/mapbox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,8 @@ test("mapbox", (t) => {

t.test('does not POST event when previously stored data is on the same day', (t) => {
const now = +Date.now();

window.localStorage.setItem(`mapbox.eventData.uuid:${config.ACCESS_TOKEN}`, uuid());
window.localStorage.setItem(`mapbox.eventData:${config.ACCESS_TOKEN}`, JSON.stringify({
anonId: uuid(),
lastSuccess: now
}));

Expand All @@ -396,8 +395,8 @@ test("mapbox", (t) => {
t.test('POSTs event when previously stored anonId is not a valid uuid', (t) => {
const now = +Date.now();

window.localStorage.setItem(`mapbox.turnstileEventData:${config.ACCESS_TOKEN}`, JSON.stringify({
anonId: 'anonymous',
window.localStorage.setItem(`mapbox.eventData.uuid:${config.ACCESS_TOKEN}`, 'anonymous');
window.localStorage.setItem(`mapbox.eventData:${config.ACCESS_TOKEN}`, JSON.stringify({
lastSuccess: now
}));

Expand All @@ -414,8 +413,8 @@ test("mapbox", (t) => {
t.test('POSTs event when previously stored timestamp is more than 24 hours in the future', (t) => {
const now = +Date.now();

window.localStorage.setItem(`mapbox.turnstileEventData:${config.ACCESS_TOKEN}`, JSON.stringify({
anonId: uuid(),
window.localStorage.setItem(`mapbox.eventData.uuid:${config.ACCESS_TOKEN}`, uuid());
window.localStorage.setItem(`mapbox.eventData:${config.ACCESS_TOKEN}`, JSON.stringify({
lastSuccess: now + ms25Hours // 24-hours later
}));

Expand Down Expand Up @@ -687,7 +686,7 @@ test("mapbox", (t) => {
});

t.test('POSTs event when previously stored anonId is not a valid uuid', (t) => {
window.localStorage.setItem(`mapbox.turnstileEventData:${config.ACCESS_TOKEN}`, JSON.stringify({
window.localStorage.setItem(`mapbox.eventData.uuid:${config.ACCESS_TOKEN}`, JSON.stringify({
anonId: 'anonymous'
}));

Expand Down

0 comments on commit 997aec6

Please sign in to comment.