Skip to content

Instantly share code, notes, and snippets.

@maitrungduc1410
Last active March 14, 2019 08:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maitrungduc1410/782ef4c39e90d51786bb5a138d9ee6fc to your computer and use it in GitHub Desktop.
Save maitrungduc1410/782ef4c39e90d51786bb5a138d9ee6fc to your computer and use it in GitHub Desktop.
SG_DECODING_WEBSITE
MONGO_ROOT_USERNAME=root
MONGO_ROOT_PASSWORD=ce2pFD2jJNmqNJkG
MONGO_HOST=localhost
MONGO_PORT=27017
APP_MONGO_DB=sg-decoding
APP_MONGO_USER=user
APP_MONGO_PASS=ZfQDwQYN4T6PQARY
echo 'Creating application user and db'
mongo ${APP_MONGO_DB} \
--host localhost \
--port ${MONGO_PORT} \
-u ${MONGO_ROOT_USER} \
-p ${MONGO_ROOT_PASS} \
--authenticationDatabase admin \
--eval "db.createUser({user: '${APP_MONGO_USER}', pwd: '${APP_MONGO_PASS}', roles:[{role:'dbOwner', db: '${APP_MONGO_DB}'}]});"
version: '2.1'
services:
# decoder: # uncomment to enable this service
# image: speechlab.azurecr.io/sgenglish-offline-decoding:1.0
# restart: unless-stopped
# volumes:
# # Uncomment to include custom plugins
# - ./user/input:/workspace/input
# - ./user/output:/workspace/output
# command: /workspace/entry_point.sh
# sud: # uncomment to enable this service
# image: speechlab.azurecr.io/sgenglish-offline-decoding-sud:1.0
# restart: unless-stopped
# volumes:
# # Uncomment to include custom plugins
# - /workspace/user/output:/workspace/output
# ports:
# - "6000:6000"
# command: /workspace/sud/start_sud.sh
# -----------------
backend:
image: maitrungduc1410/sg-decoding-backend:latest
restart: unless-stopped
ports:
- "3000:3000"
# volumes:
# - ./log/backend:/workspace/website/backend/log # mount only API log
# - ./audios:/workspace/website/backend/public/audios # mount audio inputs and outputs
depends_on: # start backend after db is started
- db
command: npm run prod
frontend:
image: maitrungduc1410/sg-decoding-frontend:latest
restart: unless-stopped
ports:
- "80:80"
# volumes:
# - ./log/frontend:/var/log/nginx # mount webserver log (contains all API and resources log)
db:
container_name: db
image: mongo
volumes:
- ./db-entrypoint/:/docker-entrypoint-initdb.d/
- ./data:/data/db
ports:
- "27017:27017"
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_ROOT_USERNAME}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_ROOT_PASSWORD}
- APP_MONGO_HOST=${MONGO_HOST}
- MONGO_PORT=${MONGO_PORT}
- MONGO_ROOT_USER=${MONGO_ROOT_USERNAME}
- MONGO_ROOT_PASS=${MONGO_ROOT_PASSWORD}
- APP_MONGO_USER=${APP_MONGO_USER}
- APP_MONGO_PASS=${APP_MONGO_PASS}
- APP_MONGO_DB=${APP_MONGO_DB}
restart: unless-stopped
// copy file to server using scp with format -->> client.scp('file.txt', 'admin:password@example.com:port:/home/admin/', function(err) {})
client.scp(`${env.storage}/${res.req.file.filename}`, `${env.serverStorage[storageName].admin}:${env.serverStorage[storageName].password}@${env.serverStorage[storageName].host}:${env.serverStorage[storageName].port}:${env.serverStorage[storageName].path}`, async (err) => {
if (err) {
res.status(400).send(err)
} else {
// if success, do some actions and update to DB
let conversationName = req.params.conversationName
let duration = await getAudioDurationInSeconds(`${env.storage}/${res.req.file.filename}`)
let conversation = await ConversationController.create({
name: !conversationName || !conversationName.trim().length ? 'Note' : conversationName,
path: `${env.storage}/${res.req.file.filename}`,
duration: duration,
fileName: res.req.file.filename,
originalFileName: originalname,
storageName: storageName,
status: [{status: 'CREATED', created_at: Date.now()}],
user: user._id
})
return res.json({
message: 'success',
conversation: conversation
})
}
})
static async updateStatus(req, res) { // status received from SG-DECODING, format: {filename: 'test.mp3', status: 'DONE'}, method: POST
let fileName = req.body.filename
let status = req.body.status
let username = fileName.substr(0, fileName.indexOf('-')) // get username from filename
let conversation = await Conversation.findOne({fileName: fileName}) // because each file name created with name contains unique timestamps, so we find in DB conversation with this filename
let timeCreated = Date.now() // take current timestamp
if (conversation) { // if find one conversation
conversation.status.push({ // push status to this conversation
status: status,
created_at: timeCreated
})
let files = [] // this array contains output file from SG-DECODING
if (status.trim().toLowerCase() === 'done') { // if status is DONE -> we have output files
let storage = env.serverStorage[conversation.storageName] // get path of folder to storage output files in this app
let fileNameWithoutExtension = conversation.fileName.substring(0, conversation.fileName.length - 4)
// we download file from remote server which contains output file, return connection between this app and that server
let conn = downloadFileRecursive(storage.host, storage.port, storage.admin, storage.password, `/export/data/output/${fileNameWithoutExtension}`, env.output)
// because the process of download files from remote server is asynchronous so we need to carefully handle it
// on connection end (that mean it finishes downloading files)
await conn.on('end', () => {
files = getFilesInFolder(`${env.output}/export/data/output/${fileNameWithoutExtension}`) // because we download all file in every output folder in remote server (no need to care what inside), now when finish downloading it to our app, we browse to see what inside the output
conversation.isDone = true // set status for conversation
conversation.files = files // set output files path for conversation
conversation.save() // save conversation after edit back to DB
io.io.sockets.to(username).to('admin').emit('status', { // using Socket.IO, fire an event to only user who own this conversation and to admin (Admin can listen to all) -> to make update in realtime on frontend
fileName: fileName,
status: status,
created_at: timeCreated,
isDone: conversation.isDone,
files: files
})
return res.json({
success: true
})
})
} else { // if status is NOT Done
conversation.save() // just save conversation back after we set status for it
io.io.sockets.to(username).to('admin').emit('status', { // fire event to frontend to update
fileName: fileName,
status: status,
created_at: timeCreated,
isDone: conversation.isDone,
files: files
})
return res.json({
success: true
})
}
} else {
let message = {
message: 'File not found!'
}
return res.json(message)
}
}
@maitrungduc1410
Copy link
Author

maitrungduc1410 commented Mar 6, 2019

How to use:
< If you already run these containers in the past, down it first >
At root folder (which ever u choose is root):

  • Create docker-compose.yml file with content above
  • Create .env file with content above
  • Create folder name db-entrypoint, inside it create db-entrypoint.sh with content above
  • Run docker-compose up to bring up the app

@maitrungduc1410
Copy link
Author

maitrungduc1410 commented Mar 6, 2019

User to test (user / password):

  • admin / 123456
  • user1 / 123456
  • user2 / 123456
  • test1 / 123456
  • test2 / 123456
  • test3 / 123456

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment