Skip to content

Commit 1b1fea6

Browse files
author
春秋一语
authored
Merge pull request #17 from Coding/dashboard-dev-search
Dashboard dev search
2 parents 0d3c876 + 4ae3146 commit 1b1fea6

File tree

16 files changed

+687
-9
lines changed

16 files changed

+687
-9
lines changed

app/CodingSDK.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import * as Modal from './components/Modal/actions'
1010
import * as SideBarActions from './components/Panel/SideBar/actions'
1111
import { notify, NOTIFY_TYPE } from './components/Notification/actions'
1212
import api from '../app/backendAPI'
13-
import { closeWebsocketClient, closeTtySocketClient } from '../app/backendAPI/workspaceAPI'
13+
import { closeWebsocketClient, closeTtySocketClient, closeSearchWebsocketClient } from '../app/backendAPI/workspaceAPI'
1414
import * as Panel from './components/Panel/actions'
1515
import * as File from './commons/File'
1616
import initializeState from './containers/Initialize/state'
@@ -62,7 +62,8 @@ export default class {
6262
get socketManager () {
6363
return ({
6464
closeWebsocketClient,
65-
closeTtySocketClient
65+
closeTtySocketClient,
66+
closeSearchWebsocketClient
6667
})
6768
}
6869

app/backendAPI/searchAPI.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { SearchSocketClient } from './websocketClients'
2+
import config from 'config';
3+
4+
export function searchWorkspaceUp() {
5+
SearchSocketClient.$$singleton.send(`/app/ws/up`, {spaceKey: config.spaceKey});
6+
}
7+
8+
export function searchWorkspaceDown() {
9+
SearchSocketClient.$$singleton.send(`/app/ws/down`, {spaceKey: config.spaceKey});
10+
}
11+
12+
export function searchWorkspaceStatus() {
13+
SearchSocketClient.$$singleton.send(`/app/ws/status`, {spaceKey: config.spaceKey});
14+
}
15+
16+
export function searchString(searching, randomKey) {
17+
SearchSocketClient.$$singleton.send(`/app/search/string`, {spaceKey: config.spaceKey, randomKey: randomKey}, JSON.stringify(searching));
18+
}
19+
20+
export function searchPattern(searching, randomKey) {
21+
SearchSocketClient.$$singleton.send(`/app/search/pattern`, {spaceKey: config.spaceKey, randomKey: randomKey}, JSON.stringify(searching));
22+
}
23+
24+
export function searchInterrupt(taskId) {
25+
SearchSocketClient.$$singleton.send(`/app/search/interrupt`, {spaceKey: config.spaceKey}, taskId);
26+
}

app/backendAPI/websocketClients.js

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import emitter, * as E from 'utils/emitter'
55
import config from 'config'
66
import { autorun, runInAction } from 'mobx'
77
import { notify, NOTIFY_TYPE } from '../components/Notification/actions'
8+
import * as searchAPI from 'backendAPI/searchAPI'
89

910
const log = console.log || (x => x)
1011
const warn = console.warn || (x => x)
@@ -93,6 +94,9 @@ class FsSocketClient {
9394
if (TtySocketClient.$$singleton) {
9495
TtySocketClient.$$singleton.close();
9596
}
97+
if(SearchSocketClient.$$singleton) {
98+
SearchSocketClient.$$singleton.close();
99+
}
96100
}
97101
}
98102

@@ -179,4 +183,105 @@ class TtySocketClient {
179183
}
180184
}
181185

182-
export { FsSocketClient, TtySocketClient }
186+
class SearchSocketClient {
187+
constructor () {
188+
if (SearchSocketClient.$$singleton) return SearchSocketClient.$$singleton
189+
190+
const wsUrl = config.wsURL
191+
const firstSlashIdx = wsUrl.indexOf('/', 8)
192+
const [host, path] = firstSlashIdx === -1 ? [wsUrl, ''] : [wsUrl.substring(0, firstSlashIdx), wsUrl.substring(firstSlashIdx)]
193+
194+
// const url = `${host}:8066/search/sockjs`
195+
const url = `${host}${path}/search/sockjs/${config.spaceKey}`
196+
// http://dev.coding.ide/ide-ws/search/sockjs/kfddvb/info
197+
this.sockJSConfigs = [url, {}, {server: `${config.spaceKey}`, transports: 'websocket'}]
198+
199+
this.backoff = getBackoff({
200+
delayMin: 1500,
201+
delayMax: 10000,
202+
})
203+
this.maxAttempts = 5
204+
205+
SearchSocketClient.$$singleton = this
206+
emitter.on(E.SOCKET_RETRY, () => {
207+
this.reconnect()
208+
})
209+
}
210+
211+
connect () {
212+
if (!this.socket || !this.stompClient) {
213+
this.socket = new SockJS(...this.sockJSConfigs)
214+
this.stompClient = Stomp.over(this.socket)
215+
this.stompClient.debug = false // stop logging PING/PONG
216+
}
217+
const success = () => {
218+
runInAction(() => config.searchSocketConnected = true)
219+
this.backoff.reset()
220+
this.successCallback(this.stompClient)
221+
}
222+
const error = (frame) => {
223+
if (this.shouldClose) {
224+
this.shouldClose = false;
225+
return;
226+
}
227+
log('[SEARCH Socket] SearchSocket error', this.socket)
228+
switch (this.socket.readyState) {
229+
case SockJS.CLOSING:
230+
case SockJS.CLOSED:
231+
runInAction(() => config.searchSocketConnected = false)
232+
this.reconnect()
233+
break
234+
case SockJS.OPEN:
235+
log('FRAME ERROR', frame)
236+
break
237+
default:
238+
}
239+
this.errorCallback(frame)
240+
}
241+
242+
this.stompClient.connect({}, success, error)
243+
}
244+
245+
reconnect () {
246+
if (config.searchSocketConnected) return
247+
log(`[SEARCH Socket] reconnect searchSocket ${this.backoff.attempts}`)
248+
// unset this.socket
249+
this.socket = undefined
250+
if (this.backoff.attempts <= this.maxAttempts) {
251+
const retryDelay = this.backoff.duration()
252+
log(`Retry after ${retryDelay}ms`)
253+
const timer = setTimeout(
254+
this.connect.bind(this)
255+
, retryDelay)
256+
} else {
257+
// must emit ,ops correct?
258+
// emitter.emit(E.SOCKET_TRIED_FAILED)
259+
notify({ message: i18n`global.onSocketError`, notifyType: NOTIFY_TYPE.ERROR })
260+
this.backoff.reset()
261+
warn('Sock connected failed, something may be broken, reload page and try again')
262+
}
263+
}
264+
265+
close () {
266+
const self = this
267+
if (config.searchSocketConnected) {
268+
searchAPI.searchWorkspaceDown();
269+
self.shouldClose = true;
270+
self.socket.close();
271+
// must emit ???
272+
// emitter.emit(E.SOCKET_TRIED_FAILED);
273+
runInAction(() => config.searchSocketConnected = false);
274+
}
275+
}
276+
277+
subscribe = (topic, process) => {
278+
this.stompClient.subscribe(topic, process);
279+
}
280+
281+
send = (mapping, headers, data) => {
282+
this.stompClient.send(mapping, headers, data);
283+
}
284+
}
285+
286+
287+
export { FsSocketClient, TtySocketClient, SearchSocketClient }

app/backendAPI/workspaceAPI.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import config from '../config'
22
import { request } from '../utils'
3-
import { FsSocketClient, TtySocketClient } from './websocketClients'
3+
import { FsSocketClient, TtySocketClient, SearchSocketClient } from './websocketClients'
44

55
let connectedResolve
66
export const fsSocketConnectedPromise = new Promise((rs, rj) => connectedResolve = rs)
77

8+
let searchConnectedResolve;
9+
export const searchSocketConnectedPromise = new Promise((rs, rj) => searchConnectedResolve = rs);
10+
811
export function isWorkspaceExist () {
912
return request.get(`/workspaces/${config.spaceKey}`)
1013
.catch(() => false)
@@ -41,6 +44,18 @@ export function connectWebsocketClient () {
4144
})
4245
}
4346

47+
export function connectSearchWebsocketClient() {
48+
return new Promise((resolve) => {
49+
const searchSocketClient = new SearchSocketClient();
50+
searchSocketClient.successCallback = function(stompClient) {
51+
searchConnectedResolve(stompClient);
52+
resolve(true);
53+
}
54+
searchSocketClient.errorCallback = function(error) {}
55+
searchSocketClient.connect();
56+
})
57+
}
58+
4459
export function closeWebsocketClient () {
4560
const fsSocketClient = new FsSocketClient()
4661
fsSocketClient.close()
@@ -51,6 +66,11 @@ export function closeTtySocketClient () {
5166
ttySocketClient.close()
5267
}
5368

69+
export function closeSearchWebsocketClient() {
70+
const searchSocketClient = new SearchSocketClient();
71+
searchSocketClient.close();
72+
}
73+
5474
export function getSettings () {
5575
return request.get(`/workspaces/${config.spaceKey}/settings?base64=false`).then(({ content = {} }) => JSON.parse(content))
5676
}

app/commons/Search/action.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import * as api from 'backendAPI/searchAPI'
2+
import state from './state'
3+
4+
function searchUp() {
5+
if(!state.ws.status) {
6+
state.ws.name = spaceKey;
7+
api.searchWorkspaceUp();
8+
}
9+
}
10+
11+
function searchDown() {
12+
if(state.ws.status) {
13+
api.searchWorkspaceDown();
14+
}
15+
}
16+
17+
function searchStatus() {
18+
api.searchWorkspaceStatus();
19+
}
20+
21+
function searchString() {
22+
if(state.ws.status) {
23+
commonSearch();
24+
api.searchString(state.searching, state.searched.randomKey);
25+
}
26+
}
27+
28+
function searchPattern() {
29+
if(state.ws.status) {
30+
commonSearch();
31+
api.searchPattern(state.searching, state.searched.randomKey);
32+
}
33+
}
34+
35+
function commonSearch() {
36+
if(!state.searched.end && !state.ws.first) {
37+
api.searchInterrupt(state.searched.taskId);
38+
}
39+
if(state.searched.taskId != null) {
40+
state.searched.former.taskId = state.searched.taskId
41+
state.searched.former.results = state.searched.results.splice(0, state.searched.results.length);
42+
state.searched.taskId = ''
43+
}
44+
state.searched.taskId = ''
45+
state.searched.pattern = state.searching.isPattern
46+
state.searched.message = ''
47+
state.searched.end = false
48+
state.searched.randomKey = randomForOne()
49+
}
50+
51+
function searchInterrupt() {
52+
if(state.ws.status
53+
&& !state.searched.end) {
54+
api.searchInterrupt(state.searched.taskId);
55+
}
56+
}
57+
58+
function randomForOne() {
59+
return Math.random().toString(36)
60+
}
61+
62+
export { searchUp, searchDown, searchStatus, searchString, searchPattern, searchInterrupt }

app/commons/Search/state.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { observable } from 'mobx'
2+
3+
export const ws = observable({
4+
name: '',
5+
status: false,
6+
first: true
7+
})
8+
9+
export const searching = observable({
10+
pattern: '',
11+
path: '',
12+
caseSensitive: false,
13+
word: false,
14+
isPattern: false,
15+
singleFork: false
16+
})
17+
18+
export const searched = observable({
19+
taskId: '',
20+
randomKey: '',
21+
pattern: false,
22+
message: '',
23+
results: [],
24+
end: false,
25+
former: {
26+
taskId: '',
27+
results: []
28+
}
29+
})
30+
31+
const state = {
32+
ws,
33+
searching,
34+
searched
35+
}
36+
37+
export default state;

0 commit comments

Comments
 (0)