Update application code

This commit is contained in:
Pavel Murygin 2021-09-10 02:04:29 +03:00
parent fd7fadb2a9
commit 3c36e3a95b
8 changed files with 517 additions and 484 deletions

View File

@ -1,12 +1,12 @@
module App
import PeerId, Op, Peer from "@fluencelabs/aqua-lib/builtin.aqua"
import AppConfig, FluentPad from "fluent-pad.aqua"
import AppConfig, UserStatus, TextState from "fluent-pad.aqua"
import User, UserList, AuthResult from "user-list.aqua"
import EmptyServiceResult from "common.aqua"
import History, GetEntriesServiceResult, AddServiceResult from "history.aqua"
export join, getUserList, initAfterJoin, updateOnlineStatuses, leave, auth, getHistory, addEntry, FluentPad, AppConfig
export join, getUserList, initAfterJoin, updateOnlineStatuses, leave, auth, getHistory, addEntry, UserStatus, TextState, AppConfig
func join(user: User) -> EmptyServiceResult:
app <- AppConfig.getApp()
@ -29,10 +29,10 @@ func initAfterJoin(me: User) -> []User:
isOnline <- Peer.is_connected(user.peer_id)
if isOnline:
on user.peer_id via user.relay_id:
FluentPad.notifyUserAdded(me, true)
UserStatus.notifyUserAdded(me, true)
-- else:
--` Op.identity("dontcare")
par FluentPad.notifyUserAdded(user, isOnline)
par UserStatus.notifyUserAdded(user, isOnline)
<- allUsers
@ -41,17 +41,17 @@ func updateOnlineStatuses():
for user <- allUsers par:
on user.peer_id via user.relay_id:
isOnline <- Peer.is_connected(user.peer_id)
FluentPad.notifyOnline(user.peer_id, isOnline)
UserStatus.notifyOnline(user.peer_id, isOnline)
func leave():
app <- AppConfig.getApp()
on app.user_list.peer_id:
UserList app.user_list.service_id
res <- UserList.leave(%init_peer_id%)
res <- UserList.leave(INIT_PEER_ID)
allUsers <- getUserList()
for user <- allUsers par:
on user.peer_id via user.relay_id:
FluentPad.notifyUserRemoved(%init_peer_id%)
UserStatus.notifyUserRemoved(INIT_PEER_ID)
func auth() -> AuthResult:
app <- AppConfig.getApp()
@ -76,7 +76,7 @@ func addEntry(entry: string) -> AddServiceResult:
res <- History.add(entry, authRes.is_authenticated)
allUsers <- getUserList()
for user <- allUsers par:
if user.peer_id != %init_peer_id%:
if user.peer_id != INIT_PEER_ID:
on user.peer_id via user.relay_id:
FluentPad.notifyTextUpdate(entry, authRes.is_authenticated)
TextState.notifyTextUpdate(entry, authRes.is_authenticated)
<- res

View File

@ -1,4 +1,4 @@
module FluentPad declares AppConfig, FluentPad
module FluentPad declares AppConfig, UserStatus, TextState
import PeerId from "@fluencelabs/aqua-lib/builtin.aqua"
import User from "user-list.aqua"
@ -11,10 +11,12 @@ data App:
history: ServiceInstance
user_list: ServiceInstance
service FluentPad("fluence/fluent-pad"):
service UserStatus("fluence/fluent-pad/status"):
notifyOnline(userPeerId: string, isOnline: bool)
notifyUserAdded(currentUser: User, isOnline: bool)
notifyUserRemoved(userPeerId: PeerId)
service TextState("fluence/fluent-pad/text-state"):
notifyTextUpdate(changes: string, isAuthorized: bool)
service AppConfig("fluence/get-config"):

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,6 @@
import config from 'src/app.json';
import { krasnodar } from '@fluencelabs/fluence-network-environment';
export const fluentPadServiceId = 'fluence/fluent-pad';
export const notifyOnlineFnName = 'notifyOnline';
export const notifyUserAddedFnName = 'notifyUserAdded';
export const notifyUserRemovedFnName = 'notifyUserRemoved';
export const notifyTextUpdateFnName = 'notifyTextUpdate';
export const userList = {
peer_id: config.services.user_list.node,
service_id: config.services.user_list.id,
@ -23,7 +16,7 @@ export const fluentPadApp = {
history: history,
};
// export const relayNode = testNet[0];
// export const relayNode = krasnodar[0];
export const relayNode = {
multiaddr: '/ip4/127.0.0.1/tcp/4310/ws/p2p/12D3KooWKEprYXUXqoV5xSBeyqrWLpQLLH4PXfvVkDJtmcqmh5V3',
peerId: '12D3KooWKEprYXUXqoV5xSBeyqrWLpQLLH4PXfvVkDJtmcqmh5V3',

View File

@ -7,42 +7,44 @@ import { UserList } from './UserList';
import { CollaborativeEditor } from './CollaborativeEditor';
import { fluentPadApp, relayNode } from 'src/app/constants';
import { CheckResponse, withErrorHandlingAsync } from './util';
import { join, leave } from 'src/_aqua/app';
import { join, leave, registerAppConfig } from 'src/_aqua/app';
const createClientEx = async (relay) => {
const client = await createClient(relay);
client.aquaCallHandler.on('fluence/get-config', 'getApp', () => {
return fluentPadApp;
});
client.aquaCallHandler.on('fluence/get-config', 'get_init_peer_id', () => {
return client.selfPeerId;
});
client.aquaCallHandler.on('fluence/get-config', 'get_init_relay', () => {
return client.relayPeerId!;
});
return client;
};
const App = () => {
const [client, setClient] = useState<FluenceClient | null>(null);
const [isConnected, setIsConnected] = useState<boolean>(false);
const [isInRoom, setIsInRoom] = useState<boolean>(false);
const [nickName, setNickName] = useState('');
const connect = async () => {
try {
await FluencePeer.default.init({ connectTo: relayNode });
setIsConnected(true);
registerAppConfig({
getApp: () => {
return fluentPadApp
},
})
}
catch (err) {
console.log('Peer initialization failed', err)
}
}
useEffect(() => {
createClientEx(relayNode)
.then((client) => setClient(client))
.catch((err) => console.log('Client initialization failed', err));
connect()
}, []);
const joinRoom = async () => {
if (!client) {
if (!isConnected) {
return;
}
await withErrorHandlingAsync(async () => {
const res = await join(client, {
peer_id: client.selfPeerId,
relay_id: client.relayPeerId!,
const res = await join( {
peer_id: FluencePeer.default.connectionInfo.selfPeerId,
relay_id: FluencePeer.default.connectionInfo.connectedRelay!,
name: nickName,
});
if (CheckResponse(res)) {
@ -52,18 +54,18 @@ const App = () => {
};
const leaveRoom = async () => {
if (!client) {
if (!isConnected) {
return;
}
await withErrorHandlingAsync(async () => {
await leave(client);
await leave();
setIsInRoom(false);
});
};
return (
<FluenceClientContext.Provider value={client}>
<>
<div className="header-wrapper">
<div className="header">
<div className="header-item">
@ -75,7 +77,7 @@ const App = () => {
</div>
<div className="header-item">
Connection status: {client ? <span className="accent">connected</span> : 'disconnected'}
Connection status: {isConnected ? <span className="accent">connected</span> : 'disconnected'}
</div>
</div>
</div>
@ -105,7 +107,7 @@ const App = () => {
<input
type="submit"
className="join-button"
disabled={isInRoom || !client || !nickName}
disabled={isInRoom || !isConnected || !nickName}
value="Join"
/>
</form>
@ -120,7 +122,7 @@ const App = () => {
)}
</div>
</div>
</FluenceClientContext.Provider>
</>
);
};

View File

@ -1,12 +1,9 @@
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { PeerIdB58, subscribeToEvent } from '@fluencelabs/fluence';
import { fluentPadServiceId, notifyTextUpdateFnName } from 'src/app/constants';
import { useFluenceClient } from '../app/FluenceClientContext';
import { getUpdatedDocFromText, initDoc, SyncClient } from '../app/sync';
import { withErrorHandlingAsync } from './util';
import { addEntry, getHistory } from 'src/aqua/app';
import { addEntry, getHistory, registerTextState } from 'src/_aqua/app';
const broadcastUpdates = _.debounce((text: string, syncClient: SyncClient) => {
let doc = syncClient.getDoc();
@ -17,7 +14,6 @@ const broadcastUpdates = _.debounce((text: string, syncClient: SyncClient) => {
}, 100);
export const CollaborativeEditor = () => {
const client = useFluenceClient()!;
const [text, setText] = useState<string | null>(null);
const [syncClient, setSyncClient] = useState(new SyncClient());
@ -28,7 +24,7 @@ export const CollaborativeEditor = () => {
syncClient.handleSendChanges = (changes: string) => {
withErrorHandlingAsync(async () => {
const res = await addEntry(client, changes);
const res = await addEntry(changes);
if (res.ret_code !== 0) {
throw new Error(
`Failed to add message to history service, code=${res.ret_code}, message=${res.err_msg}`,
@ -37,19 +33,19 @@ export const CollaborativeEditor = () => {
});
};
const unsub = subscribeToEvent(client, fluentPadServiceId, notifyTextUpdateFnName, (args, tetraplets) => {
const [changes, isAuthorized] = args as [string, boolean];
if (changes) {
syncClient.receiveChanges(changes);
registerTextState({
notifyTextUpdate: (changes, isAuthorized) => {
if (changes) {
syncClient.receiveChanges(changes);
}
}
});
})
syncClient.start();
// don't block
withErrorHandlingAsync(async () => {
const res = await getHistory(client);
const res = await getHistory();
for (let e of res.entries) {
syncClient.receiveChanges(e.body);
}
@ -60,7 +56,6 @@ export const CollaborativeEditor = () => {
});
return () => {
unsub();
syncClient.stop();
};
}, []);

View File

@ -1,14 +1,10 @@
import { useEffect, useState } from 'react';
import {
fluentPadServiceId,
notifyOnlineFnName,
notifyUserAddedFnName,
notifyUserRemovedFnName,
} from 'src/app/constants';
import { useFluenceClient } from '../app/FluenceClientContext';
import { PeerIdB58, subscribeToEvent } from '@fluencelabs/fluence';
import { withErrorHandlingAsync } from './util';
import { initAfterJoin, updateOnlineStatuses } from 'src/aqua/app';
import { initAfterJoin, updateOnlineStatuses } from 'src/_aqua/app';
import { registerUserStatus } from 'src/_aqua/app';
import { FluencePeer, PeerIdB58 } from '@fluencelabs/fluence';
interface User {
id: PeerIdB58;
@ -16,16 +12,9 @@ interface User {
isOnline: boolean;
}
interface ApiUser {
name: string;
peer_id: string;
relay_id: string;
}
const refreshOnlineStatusTimeoutMs = 10000;
export const UserList = (props: { selfName: string }) => {
const client = useFluenceClient()!;
const [users, setUsers] = useState<Map<PeerIdB58, User>>(new Map());
const updateOnlineStatus = (user, onlineStatus) => {
@ -42,12 +31,15 @@ export const UserList = (props: { selfName: string }) => {
useEffect(() => {
const listRefreshTimer = setInterval(() => {
withErrorHandlingAsync(async () => {
// await updateOnlineStatuses(client);
await updateOnlineStatuses();
});
}, refreshOnlineStatusTimeoutMs);
const unsub1 = subscribeToEvent(client, fluentPadServiceId, notifyUserAddedFnName, (args, _) => {
const [user, isOnline] = args as [ApiUser, boolean];
registerUserStatus({
notifyOnline: (user, onlineStatus) => {
updateOnlineStatus(user, onlineStatus);
},
notifyUserAdded: (user, isOnline) => {
setUsers((prev) => {
const u = user;
const result = new Map(prev);
@ -63,36 +55,29 @@ export const UserList = (props: { selfName: string }) => {
return result;
});
});
},
const unsub2 = subscribeToEvent(client, fluentPadServiceId, notifyUserRemovedFnName, (args, _) => {
const [userLeft] = args as [PeerIdB58];
notifyUserRemoved: (userLeft) => {
setUsers((prev) => {
const result = new Map(prev);
result.delete(userLeft);
return result;
});
});
}
})
const unsub3 = subscribeToEvent(client, fluentPadServiceId, notifyOnlineFnName, (args, _) => {
const [user, onlineStatus] = args as [PeerIdB58, boolean];
updateOnlineStatus(user, onlineStatus);
});
// don't block
withErrorHandlingAsync(async () => {
await initAfterJoin(client, {
await initAfterJoin({
name: props.selfName,
peer_id: client.selfPeerId,
relay_id: client.relayPeerId!,
peer_id: FluencePeer.default.connectionInfo.selfPeerId,
relay_id: FluencePeer.default.connectionInfo.connectedRelay!,
});
});
return () => {
clearTimeout(listRefreshTimer);
unsub1();
unsub2();
unsub3();
};
}, []);
@ -105,7 +90,7 @@ export const UserList = (props: { selfName: string }) => {
<ul>
{usersArray.map((x) => (
<li key={x.id}>
<span className={x.id === client.selfPeerId ? 'bold' : ''}>{x.name}</span>
<span className={x.id === FluencePeer.default.connectionInfo.selfPeerId ? 'bold' : ''}>{x.name}</span>
<span className={x.isOnline ? 'green' : 'red'}> ({x.isOnline ? 'online' : 'offline'})</span>
</li>
))}

0
deploy_docker.sh Normal file → Executable file
View File