user health no err

This commit is contained in:
boufni95 2024-12-12 18:59:25 +00:00
parent 84b3ef4b9d
commit 93af9969ed
11 changed files with 234 additions and 192 deletions

View file

@ -263,7 +263,7 @@ The nostr server will send back a message response, and inside the body there wi
- UserHealth - UserHealth
- auth type: __User__ - auth type: __User__
- This methods has an __empty__ __request__ body - This methods has an __empty__ __request__ body
- This methods has an __empty__ __response__ body - output: [UserHealthState](#UserHealthState)
# HTTP API DEFINITION # HTTP API DEFINITION
@ -817,7 +817,7 @@ The nostr server will send back a message response, and inside the body there wi
- http method: __post__ - http method: __post__
- http route: __/api/user/health__ - http route: __/api/user/health__
- This methods has an __empty__ __request__ body - This methods has an __empty__ __request__ body
- This methods has an __empty__ __response__ body - output: [UserHealthState](#UserHealthState)
# INPUTS AND OUTPUTS # INPUTS AND OUTPUTS
@ -1291,6 +1291,9 @@ The nostr server will send back a message response, and inside the body there wi
### UseInviteLinkRequest ### UseInviteLinkRequest
- __invite_token__: _string_ - __invite_token__: _string_
### UserHealthState
- __downtime_reason__: _string_
### UserInfo ### UserInfo
- __balance__: _number_ - __balance__: _number_
- __bridge_url__: _string_ - __bridge_url__: _string_

View file

@ -125,7 +125,7 @@ type Client struct {
UpdateChannelPolicy func(req UpdateChannelPolicyRequest) error UpdateChannelPolicy func(req UpdateChannelPolicyRequest) error
UpdateUserOffer func(req OfferConfig) error UpdateUserOffer func(req OfferConfig) error
UseInviteLink func(req UseInviteLinkRequest) error UseInviteLink func(req UseInviteLinkRequest) error
UserHealth func() error UserHealth func() (*UserHealthState, error)
} }
func NewClient(params ClientParams) *Client { func NewClient(params ClientParams) *Client {
@ -1904,26 +1904,31 @@ func NewClient(params ClientParams) *Client {
} }
return nil return nil
}, },
UserHealth: func() error { UserHealth: func() (*UserHealthState, error) {
auth, err := params.RetrieveUserAuth() auth, err := params.RetrieveUserAuth()
if err != nil { if err != nil {
return err return nil, err
} }
finalRoute := "/api/user/health" finalRoute := "/api/user/health"
body := []byte{} body := []byte{}
resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth) resBody, err := doPostRequest(params.BaseURL+finalRoute, body, auth)
if err != nil { if err != nil {
return err return nil, err
} }
result := ResultError{} result := ResultError{}
err = json.Unmarshal(resBody, &result) err = json.Unmarshal(resBody, &result)
if err != nil { if err != nil {
return err return nil, err
} }
if result.Status == "ERROR" { if result.Status == "ERROR" {
return fmt.Errorf(result.Reason) return nil, fmt.Errorf(result.Reason)
} }
return nil res := UserHealthState{}
err = json.Unmarshal(resBody, &res)
if err != nil {
return nil, err
}
return &res, nil
}, },
} }
} }

View file

@ -555,6 +555,9 @@ type UsageMetrics struct {
type UseInviteLinkRequest struct { type UseInviteLinkRequest struct {
Invite_token string `json:"invite_token"` Invite_token string `json:"invite_token"`
} }
type UserHealthState struct {
Downtime_reason string `json:"downtime_reason"`
}
type UserInfo struct { type UserInfo struct {
Balance int64 `json:"balance"` Balance int64 `json:"balance"`
Bridge_url string `json:"bridge_url"` Bridge_url string `json:"bridge_url"`

View file

@ -612,7 +612,7 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
throw new Error('method UserHealth not found' ) throw new Error('method UserHealth not found' )
} else { } else {
opStats.validate = opStats.guard opStats.validate = opStats.guard
await methods.UserHealth({...operation, ctx}); responses.push({ status: 'OK' }) const res = await methods.UserHealth({...operation, ctx}); responses.push({ status: 'OK', ...res })
opStats.handle = process.hrtime.bigint() opStats.handle = process.hrtime.bigint()
callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
} }
@ -1799,9 +1799,9 @@ export default (methods: Types.ServerMethods, opts: ServerOptions) => {
stats.validate = stats.guard stats.validate = stats.guard
const query = req.query const query = req.query
const params = req.params const params = req.params
await methods.UserHealth({rpcName:'UserHealth', ctx:authContext }) const response = await methods.UserHealth({rpcName:'UserHealth', ctx:authContext })
stats.handle = process.hrtime.bigint() stats.handle = process.hrtime.bigint()
res.json({status: 'OK'}) res.json({status: 'OK', ...response})
opts.metricsCallback([{ ...info, ...stats, ...authContext }]) opts.metricsCallback([{ ...info, ...stats, ...authContext }])
} catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } } catch (ex) { const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
}) })

View file

@ -910,14 +910,17 @@ export default (params: ClientParams) => ({
} }
return { status: 'ERROR', reason: 'invalid response' } return { status: 'ERROR', reason: 'invalid response' }
}, },
UserHealth: async (): Promise<ResultError | ({ status: 'OK' })> => { UserHealth: async (): Promise<ResultError | ({ status: 'OK' }& Types.UserHealthState)> => {
const auth = await params.retrieveUserAuth() const auth = await params.retrieveUserAuth()
if (auth === null) throw new Error('retrieveUserAuth() returned null') if (auth === null) throw new Error('retrieveUserAuth() returned null')
let finalRoute = '/api/user/health' let finalRoute = '/api/user/health'
const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } }) const { data } = await axios.post(params.baseUrl + finalRoute, {}, { headers: { 'authorization': auth } })
if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'ERROR' && typeof data.reason === 'string') return data
if (data.status === 'OK') { if (data.status === 'OK') {
return data const result = data
if(!params.checkResult) return { status: 'OK', ...result }
const error = Types.UserHealthStateValidate(result)
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
} }
return { status: 'ERROR', reason: 'invalid response' } return { status: 'ERROR', reason: 'invalid response' }
}, },

View file

@ -701,14 +701,17 @@ export default (params: NostrClientParams, send: (to:string, message: NostrRequ
} }
return { status: 'ERROR', reason: 'invalid response' } return { status: 'ERROR', reason: 'invalid response' }
}, },
UserHealth: async (): Promise<ResultError | ({ status: 'OK' })> => { UserHealth: async (): Promise<ResultError | ({ status: 'OK' }& Types.UserHealthState)> => {
const auth = await params.retrieveNostrUserAuth() const auth = await params.retrieveNostrUserAuth()
if (auth === null) throw new Error('retrieveNostrUserAuth() returned null') if (auth === null) throw new Error('retrieveNostrUserAuth() returned null')
const nostrRequest: NostrRequest = {} const nostrRequest: NostrRequest = {}
const data = await send(params.pubDestination, {rpcName:'UserHealth',authIdentifier:auth, ...nostrRequest }) const data = await send(params.pubDestination, {rpcName:'UserHealth',authIdentifier:auth, ...nostrRequest })
if (data.status === 'ERROR' && typeof data.reason === 'string') return data if (data.status === 'ERROR' && typeof data.reason === 'string') return data
if (data.status === 'OK') { if (data.status === 'OK') {
return data const result = data
if(!params.checkResult) return { status: 'OK', ...result }
const error = Types.UserHealthStateValidate(result)
if (error === null) { return { status: 'OK', ...result } } else return { status: 'ERROR', reason: error.message }
} }
return { status: 'ERROR', reason: 'invalid response' } return { status: 'ERROR', reason: 'invalid response' }
}, },

View file

@ -494,7 +494,7 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
throw new Error('method not defined: UserHealth') throw new Error('method not defined: UserHealth')
} else { } else {
opStats.validate = opStats.guard opStats.validate = opStats.guard
await methods.UserHealth({...operation, ctx}); responses.push({ status: 'OK' }) const res = await methods.UserHealth({...operation, ctx}); responses.push({ status: 'OK', ...res })
opStats.handle = process.hrtime.bigint() opStats.handle = process.hrtime.bigint()
callsMetrics.push({ ...opInfo, ...opStats, ...ctx }) callsMetrics.push({ ...opInfo, ...opStats, ...ctx })
} }
@ -1114,9 +1114,9 @@ export default (methods: Types.ServerMethods, opts: NostrOptions) => {
stats.guard = process.hrtime.bigint() stats.guard = process.hrtime.bigint()
authCtx = authContext authCtx = authContext
stats.validate = stats.guard stats.validate = stats.guard
await methods.UserHealth({rpcName:'UserHealth', ctx:authContext }) const response = await methods.UserHealth({rpcName:'UserHealth', ctx:authContext })
stats.handle = process.hrtime.bigint() stats.handle = process.hrtime.bigint()
res({status: 'OK'}) res({status: 'OK', ...response})
opts.metricsCallback([{ ...info, ...stats, ...authContext }]) opts.metricsCallback([{ ...info, ...stats, ...authContext }])
}catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e } }catch(ex){ const e = ex as any; logErrorAndReturnResponse(e, e.message || e, res, logger, { ...info, ...stats, ...authCtx }, opts.metricsCallback); if (opts.throwErrors) throw e }
break break

View file

@ -274,7 +274,7 @@ export type UseInviteLink_Input = {rpcName:'UseInviteLink', req: UseInviteLinkRe
export type UseInviteLink_Output = ResultError | { status: 'OK' } export type UseInviteLink_Output = ResultError | { status: 'OK' }
export type UserHealth_Input = {rpcName:'UserHealth'} export type UserHealth_Input = {rpcName:'UserHealth'}
export type UserHealth_Output = ResultError | { status: 'OK' } export type UserHealth_Output = ResultError | ({ status: 'OK' } & UserHealthState)
export type ServerMethods = { export type ServerMethods = {
AddApp?: (req: AddApp_Input & {ctx: AdminContext }) => Promise<AuthApp> AddApp?: (req: AddApp_Input & {ctx: AdminContext }) => Promise<AuthApp>
@ -347,7 +347,7 @@ export type ServerMethods = {
UpdateChannelPolicy?: (req: UpdateChannelPolicy_Input & {ctx: AdminContext }) => Promise<void> UpdateChannelPolicy?: (req: UpdateChannelPolicy_Input & {ctx: AdminContext }) => Promise<void>
UpdateUserOffer?: (req: UpdateUserOffer_Input & {ctx: UserContext }) => Promise<void> UpdateUserOffer?: (req: UpdateUserOffer_Input & {ctx: UserContext }) => Promise<void>
UseInviteLink?: (req: UseInviteLink_Input & {ctx: GuestWithPubContext }) => Promise<void> UseInviteLink?: (req: UseInviteLink_Input & {ctx: GuestWithPubContext }) => Promise<void>
UserHealth?: (req: UserHealth_Input & {ctx: UserContext }) => Promise<void> UserHealth?: (req: UserHealth_Input & {ctx: UserContext }) => Promise<UserHealthState>
} }
export enum AddressType { export enum AddressType {
@ -3169,6 +3169,24 @@ export const UseInviteLinkRequestValidate = (o?: UseInviteLinkRequest, opts: Use
return null return null
} }
export type UserHealthState = {
downtime_reason: string
}
export const UserHealthStateOptionalFields: [] = []
export type UserHealthStateOptions = OptionsBaseMessage & {
checkOptionalsAreSet?: []
downtime_reason_CustomCheck?: (v: string) => boolean
}
export const UserHealthStateValidate = (o?: UserHealthState, opts: UserHealthStateOptions = {}, path: string = 'UserHealthState::root.'): Error | null => {
if (opts.checkOptionalsAreSet && opts.allOptionalsAreSet) return new Error(path + ': only one of checkOptionalsAreSet or allOptionalNonDefault can be set for each message')
if (typeof o !== 'object' || o === null) return new Error(path + ': object is not an instance of an object or is null')
if (typeof o.downtime_reason !== 'string') return new Error(`${path}.downtime_reason: is not a string`)
if (opts.downtime_reason_CustomCheck && !opts.downtime_reason_CustomCheck(o.downtime_reason)) return new Error(`${path}.downtime_reason: custom check failed`)
return null
}
export type UserInfo = { export type UserInfo = {
balance: number balance: number
bridge_url: string bridge_url: string

View file

@ -364,7 +364,7 @@ service LightningPub {
// </App> // </App>
// <User> // <User>
rpc UserHealth(structs.Empty)returns(structs.Empty){ rpc UserHealth(structs.Empty)returns(structs.UserHealthState){
option (auth_type) = "User"; option (auth_type) = "User";
option (http_method) = "post"; option (http_method) = "post";
option (http_route) = "/api/user/health"; option (http_route) = "/api/user/health";

View file

@ -15,6 +15,10 @@ message EncryptionExchangeRequest {
string deviceId = 2; string deviceId = 2;
} }
message UserHealthState {
string downtime_reason = 1;
}
message UsageMetric { message UsageMetric {
int64 processed_at_ms = 1; int64 processed_at_ms = 1;
int64 parsed_in_nano = 2; int64 parsed_in_nano = 2;

View file

@ -73,7 +73,10 @@ export default (mainHandler: Main): Types.ServerMethods => {
if (err != null) throw new Error(err.message) if (err != null) throw new Error(err.message)
await mainHandler.paymentManager.SetMockInvoiceAsPaid(req) await mainHandler.paymentManager.SetMockInvoiceAsPaid(req)
}, },
UserHealth: async () => { await mainHandler.lnd.Health() }, UserHealth: async () => {
try { await mainHandler.lnd.Health(); return { downtime_reason: "" } }
catch (e: any) { return { downtime_reason: e.message } }
},
GetUserInfo: ({ ctx }) => mainHandler.appUserManager.GetUserInfo(ctx), GetUserInfo: ({ ctx }) => mainHandler.appUserManager.GetUserInfo(ctx),
UpdateCallbackUrl: async ({ ctx, req }) => { UpdateCallbackUrl: async ({ ctx, req }) => {
return mainHandler.appUserManager.UpdateCallbackUrl(ctx, req) return mainHandler.appUserManager.UpdateCallbackUrl(ctx, req)