Compare commits

..

10 Commits

Author SHA1 Message Date
b
675a763af3 Merge pull request 'New Release' (#200) from staging into main
All checks were successful
Release to Production / build_and_release (push) Successful in 1m13s
Reviewed-on: #200
Reviewed-by: enes <enes@noreply.git.nostrdev.com>
2024-09-12 12:17:47 +00:00
bf1b3beb63 Merge branch 'main' into staging
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m17s
2024-09-12 12:09:40 +00:00
32a6f9d7a3 Merge pull request #199 from hotfix-remove-loop-9-12 into staging
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m16s
Reviewed-on: #199
Reviewed-by: eugene <eugene@nostrdev.com>
2024-09-12 09:32:54 +00:00
5f0234a358 fix: remove unstable fetch events loop
All checks were successful
Open PR on Staging / audit_and_check (pull_request) Successful in 34s
2024-09-12 11:27:55 +02:00
235e76be4e fix: processing gift wraps and notifications (#193)
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m16s
This change will potentially close multiple issues related to the gift-wrapped events processing (#168, #158). Further testing will be required to confirm before closing each.

The commented-out code causes the race condition during the processing of the gift wraps with sigits.

During the processing we perform checks to see if sigit is outdated. In cases where sigit includes multiple signers it's possible for a signer to receive multiple sigit updates at once (especially noticeable for 3rd, 4th signer). Due to async nature of processing we can have same sigit enter processing flow with different states. Since this code also updates user's app state, which includes uploads to the blossom server it takes time to upload local user state which causes both to check against the stale data and un-updated app state. This results in both sigits being "new" and both proceed to update user state and upload app data. We have no guarantees as in which event will update last, meaning that the final state we end up with could be already stale.

The issue is also complicated due to the fact that we mark the gift wraps as processed and it's impossible to update the state without creating a new gift wrap with correct state and processing it last to overwrite stale state.

This is temporary solution to stop broken sigit states until proper async implementation is ready.

Co-authored-by: b
Reviewed-on: #193
Reviewed-by: eugene <eugene@nostrdev.com>
Co-authored-by: enes <mulahasanovic@outlook.com>
Co-committed-by: enes <mulahasanovic@outlook.com>
2024-09-12 08:26:59 +00:00
e2b3dc13fb chore(git): merge pull request #192 from cache-checks-9-9 into staging
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m16s
Reviewed-on: #192
Reviewed-by: s <s@noreply.git.nostrdev.com>
2024-09-10 08:48:53 +00:00
b
0244090c6a Merge branch 'staging' into cache-checks-9-9
All checks were successful
Open PR on Staging / audit_and_check (pull_request) Successful in 35s
2024-09-09 18:44:36 +00:00
f0ba9da8af fix: outdated cache checks
All checks were successful
Open PR on Staging / audit_and_check (pull_request) Successful in 33s
2024-09-09 14:16:58 +02:00
1d1c675dd7 Merge pull request #191 from lint-0-warnings into staging
All checks were successful
Release to Staging / build_and_release (push) Successful in 1m17s
Reviewed-on: #191
Reviewed-by: s
2024-09-09 08:55:28 +00:00
70f646444b fix: add types to rootReducer, rename userRobotImage types
All checks were successful
Open PR on Staging / audit_and_check (pull_request) Successful in 34s
2024-09-09 10:19:37 +02:00
9 changed files with 42 additions and 16 deletions

View File

@ -8,7 +8,7 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 2", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:fix": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint:fix": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:staged": "eslint --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "lint:staged": "eslint --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"formatter:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"", "formatter:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",

View File

@ -109,6 +109,7 @@ export const MainLayout = () => {
if (pubkey && !hasSubscribed.current) { if (pubkey && !hasSubscribed.current) {
// Call `subscribeForSigits` only if it hasn't been called before // Call `subscribeForSigits` only if it hasn't been called before
// #193 disabled websocket subscribtion, until #194 is done
subscribeForSigits(pubkey) subscribeForSigits(pubkey)
// Mark `subscribeForSigits` as called // Mark `subscribeForSigits` as called

View File

@ -18,6 +18,10 @@ export interface RestoreState {
payload: State payload: State
} }
export interface UserLogout {
type: typeof ActionTypes.USER_LOGOUT
}
export const userLogOutAction = () => { export const userLogOutAction = () => {
return { return {
type: ActionTypes.USER_LOGOUT type: ActionTypes.USER_LOGOUT

View File

@ -1,5 +1,5 @@
import * as ActionTypes from '../actionTypes' import * as ActionTypes from '../actionTypes'
import { RestoreState } from '../actions' import { RestoreState, UserLogout } from '../actions'
export enum LoginMethods { export enum LoginMethods {
extension = 'extension', extension = 'extension',
@ -54,3 +54,4 @@ export type AuthDispatchTypes =
| UpdateKeyPair | UpdateKeyPair
| UpdateNsecBunkerPubkey | UpdateNsecBunkerPubkey
| UpdateNsecBunkerRelays | UpdateNsecBunkerRelays
| UserLogout

View File

@ -3,12 +3,15 @@ import { combineReducers } from 'redux'
import { UserAppData } from '../types' import { UserAppData } from '../types'
import * as ActionTypes from './actionTypes' import * as ActionTypes from './actionTypes'
import authReducer from './auth/reducer' import authReducer from './auth/reducer'
import { AuthState } from './auth/types' import { AuthDispatchTypes, AuthState } from './auth/types'
import metadataReducer from './metadata/reducer' import metadataReducer from './metadata/reducer'
import relaysReducer from './relays/reducer' import relaysReducer from './relays/reducer'
import { RelaysState } from './relays/types' import { RelaysDispatchTypes, RelaysState } from './relays/types'
import UserAppDataReducer from './userAppData/reducer' import UserAppDataReducer from './userAppData/reducer'
import userRobotImageReducer from './userRobotImage/reducer' import userRobotImageReducer from './userRobotImage/reducer'
import { MetadataDispatchTypes } from './metadata/types'
import { UserAppDataDispatchTypes } from './userAppData/types'
import { UserRobotImageDispatchTypes } from './userRobotImage/types'
export interface State { export interface State {
auth: AuthState auth: AuthState
@ -18,6 +21,13 @@ export interface State {
userAppData?: UserAppData userAppData?: UserAppData
} }
type AppActions =
| AuthDispatchTypes
| MetadataDispatchTypes
| UserRobotImageDispatchTypes
| RelaysDispatchTypes
| UserAppDataDispatchTypes
export const appReducer = combineReducers({ export const appReducer = combineReducers({
auth: authReducer, auth: authReducer,
metadata: metadataReducer, metadata: metadataReducer,
@ -26,8 +36,10 @@ export const appReducer = combineReducers({
userAppData: UserAppDataReducer userAppData: UserAppDataReducer
}) })
// FIXME: define types export default (
export default (state: any, action: any) => { state: ReturnType<typeof appReducer> | undefined,
action: AppActions
) => {
switch (action.type) { switch (action.type) {
case ActionTypes.USER_LOGOUT: case ActionTypes.USER_LOGOUT:
return appReducer(undefined, action) return appReducer(undefined, action)

View File

@ -1,11 +1,11 @@
import * as ActionTypes from '../actionTypes' import * as ActionTypes from '../actionTypes'
import { MetadataDispatchTypes } from './types' import { UserRobotImageDispatchTypes } from './types'
const initialState: string | null = null const initialState: string | null = null
const reducer = ( const reducer = (
state = initialState, state = initialState,
action: MetadataDispatchTypes action: UserRobotImageDispatchTypes
): string | null | undefined => { ): string | null | undefined => {
switch (action.type) { switch (action.type) {
case ActionTypes.SET_USER_ROBOT_IMAGE: case ActionTypes.SET_USER_ROBOT_IMAGE:

View File

@ -6,4 +6,4 @@ export interface SetUserRobotImage {
payload: string | null payload: string | null
} }
export type MetadataDispatchTypes = SetUserRobotImage | RestoreState export type UserRobotImageDispatchTypes = SetUserRobotImage | RestoreState

View File

@ -859,9 +859,16 @@ export const subscribeForSigits = async (pubkey: string) => {
'#p': [pubkey] '#p': [pubkey]
} }
relayController.subscribeForEvents(filter, relaySet.read, (event) => { // Process the received event synchronously
processReceivedEvent(event) // Process the received event const events = await relayController.fetchEvents(filter, relaySet.read)
}) for (const e of events) {
await processReceivedEvent(e)
}
// Async processing of the events has a race condition
// relayController.subscribeForEvents(filter, relaySet.read, (event) => {
// processReceivedEvent(event)
// })
} }
const processReceivedEvent = async (event: Event, difficulty: number = 5) => { const processReceivedEvent = async (event: Event, difficulty: number = 5) => {
@ -907,7 +914,7 @@ const processReceivedEvent = async (event: Event, difficulty: number = 5) => {
if (!meta) return if (!meta) return
updateUsersAppData(meta) await updateUsersAppData(meta)
} }
/** /**

View File

@ -6,6 +6,7 @@ import { localCache } from '../services'
import { RelayMap, RelaySet } from '../types' import { RelayMap, RelaySet } from '../types'
import { import {
DEFAULT_LOOK_UP_RELAY_LIST, DEFAULT_LOOK_UP_RELAY_LIST,
ONE_DAY_IN_MS,
ONE_WEEK_IN_MS, ONE_WEEK_IN_MS,
SIGIT_RELAY SIGIT_RELAY
} from './const' } from './const'
@ -56,7 +57,7 @@ const findRelayListInCache = async (hexKey: string): Promise<Event | null> => {
// Check if the cached event is not older than one week // Check if the cached event is not older than one week
if ( if (
cachedRelayListMetadataEvent && cachedRelayListMetadataEvent &&
isOlderThanOneWeek(cachedRelayListMetadataEvent.cachedAt) !isOlderThanOneWeek(cachedRelayListMetadataEvent.cachedAt)
) { ) {
return cachedRelayListMetadataEvent.event return cachedRelayListMetadataEvent.event
} }
@ -88,11 +89,11 @@ const getDefaultRelayMap = (): RelayMap => ({
}) })
const isOlderThanOneWeek = (cachedAt: number) => { const isOlderThanOneWeek = (cachedAt: number) => {
return Date.now() - cachedAt < ONE_WEEK_IN_MS return Date.now() - cachedAt > ONE_WEEK_IN_MS
} }
const isOlderThanOneDay = (cachedAt: number) => { const isOlderThanOneDay = (cachedAt: number) => {
return Date.now() - cachedAt < ONE_WEEK_IN_MS return Date.now() - cachedAt > ONE_DAY_IN_MS
} }
const isRelayTag = (tag: string[]): boolean => tag[0] === 'r' const isRelayTag = (tag: string[]): boolean => tag[0] === 'r'