move auth polling strategy to main thread (#546)

* #545 move auth polling strategy to main thread

* #545 remove unused

* bum v0.1.1

---------

Co-authored-by: neil molina <neil@neils-MacBook-Pro.local>
This commit is contained in:
Neil 2023-05-03 15:43:50 +08:00 committed by GitHub
parent 1a0289f7c1
commit 9f88a1bf5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 66 deletions

View file

@ -196,7 +196,7 @@ app.on("open-url", (event, url) => {
}
});
function notifyMainWindow(channel: string, data: unknown) {
export function notifyMainWindow(channel: string, data: unknown) {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send(channel, data);
}

View file

@ -5,6 +5,9 @@ import { getTeaPath } from "./tea-dir";
import { app } from "electron";
import log from "./logger";
import axios from "axios";
import get from "./v1-client";
import { DeviceAuth } from "../../src/libs/types";
import { notifyMainWindow } from "../electron";
const sessionFilePath = path.join(getTeaPath(), "tea.xyz/gui/tmp.dat");
const sessionFolder = path.join(getTeaPath(), "tea.xyz/gui");
@ -152,3 +155,44 @@ export async function writeSessionData(data: Session, force?: boolean) {
log.error(error);
}
}
let pollInterval: NodeJS.Timer | null;
let pollLoop = 0;
export async function pollAuth() {
if (!pollInterval) {
log.info("polling auth starts...");
const session = await readSessionData();
pollInterval = setInterval(async () => {
pollLoop++;
log.info("poll auth retry:", pollLoop);
let clear = false;
let success = false;
try {
const data = await get<DeviceAuth>(`/auth/device/${session.device_id}`);
if (data?.status === "SUCCESS") {
await writeSessionData({
key: data.key,
user: data.user
});
clear = true;
success = true;
} else if (pollLoop > 20 && pollInterval) {
clear = true;
}
} catch (error) {
log.error(error);
clear = true;
} finally {
if (clear) {
pollInterval && clearInterval(pollInterval);
pollInterval = null;
log.info("polling auth ends.");
}
if (success) {
log.info("updating renderer session");
notifyMainWindow("session-update", sessionMemory);
}
}
}, 2000);
}
}

View file

@ -1,6 +1,6 @@
import { ipcMain, app, BrowserWindow } from "electron";
import { deletePackageFolder, getInstalledPackages, cacheImage } from "./tea-dir";
import { readSessionData, writeSessionData } from "./auth";
import { readSessionData, writeSessionData, pollAuth } from "./auth";
import type { Packages, Session } from "../../src/libs/types";
import log from "./logger";
import { syncLogsAt } from "./v1-client";
@ -205,4 +205,13 @@ export default function initializeHandlers({ notifyMainWindow }: HandlerOptions)
log.error(error);
}
});
ipcMain.handle("poll-session", async () => {
try {
log.info("start polling");
return pollAuth();
} catch (error) {
log.error(error);
}
});
}

View file

@ -1,6 +1,6 @@
{
"name": "tea",
"version": "0.1.0",
"version": "0.1.1",
"private": true,
"description": "tea gui app",
"author": "tea.xyz",

View file

@ -1,8 +1,8 @@
<script lang="ts">
import { authStore, navStore } from "$libs/stores";
import { authStore } from "$libs/stores";
import { getSession } from "@native";
import { baseUrl } from "$libs/v1-client";
import { shellOpenExternal } from "@native";
import { shellOpenExternal, pollDeviceSession } from "@native";
import mouseLeaveDelay from "@tea/ui/lib/mouse-leave-delay";
const { user } = authStore;
@ -18,7 +18,7 @@
if (session && session.device_id) {
shellOpenExternal(`${baseUrl}/auth/user?device_id=${session.device_id}`);
authStore.pollSession();
pollDeviceSession();
} else {
throw new Error("possible no internet connection");
}

View file

@ -12,14 +12,7 @@
*/
import type { Package, Review, AirtablePost, Bottle } from "@tea/ui/types";
import {
type GUIPackage,
type DeviceAuth,
type Session,
AuthStatus,
type Packages,
type AutoUpdateStatus
} from "./types";
import type { GUIPackage, Session, Packages, AutoUpdateStatus } from "./types";
import * as mock from "./native-mock";
import { PackageStates, type InstalledPackage } from "./types";
@ -130,21 +123,6 @@ export async function getAllPosts(tag?: string): Promise<AirtablePost[]> {
}
}
export async function getDeviceAuth(deviceId: string): Promise<DeviceAuth> {
let auth: DeviceAuth = {
status: AuthStatus.UNKNOWN,
key: ""
};
try {
const data = await apiGet<DeviceAuth>(`/auth/device/${deviceId}`);
if (data) auth = data;
} catch (error) {
log.error(error);
auth = await getDeviceAuth(deviceId);
}
return auth;
}
export async function getPackageBottles(packageName: string): Promise<Bottle[]> {
try {
return withRetry(async () => {
@ -296,3 +274,11 @@ export const getAutoUpdateStatus = async (): Promise<AutoUpdateStatus> => {
return { status: "up-to-date" };
}
};
export const pollDeviceSession = async () => {
try {
await ipcRenderer.invoke("poll-session");
} catch (error) {
log.error(error);
}
};

View file

@ -326,11 +326,6 @@ export async function getAllPosts(type: string): Promise<AirtablePost[]> {
return posts;
}
export async function getDeviceAuth(deviceId: string): Promise<any> {
const data = await v1Client.get<any>(`/auth/device/${deviceId}`);
return data;
}
export async function getPackageBottles(name: string): Promise<Bottle[]> {
return [
{ name, platform: "darwin", arch: "aarch64", version: "3.39.4", bytes: 123456 },
@ -411,3 +406,7 @@ export const getAutoUpdateStatus = async (): Promise<AutoUpdateStatus> => {
export async function openPackageEntrypointInTerminal(pkg: string) {
//noop
}
export const pollDeviceSession = async () => {
console.log("do nothing");
};

View file

@ -1,10 +1,11 @@
import { writable } from "svelte/store";
import { getDeviceAuth } from "@native";
import { listenToChannel } from "@native";
import type { Developer } from "@tea/ui/types";
import type { Session } from "$libs/types";
import { getSession as electronGetSession, updateSession as electronUpdateSession } from "@native";
import { initSentry } from "../sentry";
import log from "$libs/logger";
export let session: Session | null = null;
export const getSession = async (): Promise<Session | null> => {
@ -15,7 +16,6 @@ export const getSession = async (): Promise<Session | null> => {
export default function initAuthStore() {
const user = writable<Developer | undefined>();
const sessionStore = writable<Session>({});
let pollLoop = 0;
const deviceIdStore = writable<string>("");
let deviceId = "";
@ -31,7 +31,16 @@ export default function initAuthStore() {
}
});
let timer: NodeJS.Timer | null;
listenToChannel("session-update", (data: Session) => {
log.info("session update renderer", data);
sessionStore.update((val) => ({
...val,
...data
}));
if (data.user) {
user.set(data.user);
}
});
async function updateSession(data: Session) {
sessionStore.update((val) => ({
@ -43,34 +52,6 @@ export default function initAuthStore() {
await electronUpdateSession(data);
}
async function pollSession() {
if (!timer) {
timer = setInterval(async () => {
pollLoop++;
try {
const data = await getDeviceAuth(deviceId);
if (data.status === "SUCCESS") {
updateSession({
key: data.key,
user: data.user
});
user.set(data.user!);
timer && clearInterval(timer);
timer = null;
}
} catch (error) {
console.error(error);
}
if (pollLoop > 20 && timer) {
clearInterval(timer);
pollLoop = 0;
timer = null;
}
}, 2000);
}
}
function clearSession() {
updateSession({ key: undefined, user: undefined });
user.set(undefined);
@ -81,7 +62,6 @@ export default function initAuthStore() {
session: sessionStore,
deviceId,
deviceIdStore,
pollSession,
clearSession,
updateSession
};