2013-08-16 3 views
0

Firebase에서 채팅과 같은 "대화방"을 만드는 것은 다양한 샘플에 문서화 된 것처럼 쉽습니다. 채팅의 데이터 구조에 대한 제한된 수의 Firebase 객실

, 내가 이런 걸 사용합니다 :

rooms 
    room1 
     member_count 
     members 
      user1 
      user2 
     messages 
      message1 

을하지만 지금은 객실당 참가자의 수에 제한을 만들 생성하고 싶은 말 채팅 당 3 사용자 방.

어떻게 할 수 있습니까? 자신의 문서에서

은 가장 유망한 보았다 한 가지 transactions를 사용했다. 이것이 좋은 방법인지 확인할 수 있습니까? 아니면 잘못된 접근입니까?

이와 비슷한 해결책은 무엇입니까? 이 접근 방식에 대해 언급 할 수 있다면

Firebase countRef = new Firebase("https://mychat.firebaseIO-demo.com/rooms/room1"); 
countRef.runTransaction(new Transaction.Handler() { 
    @Override 
    public Transaction.Result doTransaction(MutableData currentData) { 
     int oldMemberCount = currentData.child("member_count").getValue(Integer.class); 
     currentData.child("member_count").setValue(oldMemberCount + 1); // try to update member count 
     return Transaction.success(currentData); 
    } 

    @Override 
    public void onComplete(FirebaseError error, boolean committed, DataSnapshot currentData) { 
     if (error != null || !commited) { 
      // rollback value (how? just do nothing?) 
     } 
     else { 
      // transaction has been commited (value has already been saved?) 
      currentData.child("members").child(CURRENT_USER_UUID).setValue(CURRENT_USER_NAME); // add user to the members list 
     } 
    } 
}); 

그것은 좋은 것입니다. 또한 트랜잭션이 실패하면 해당 상황에서 만족할 수 없습니다. 동시에 가입하려는 다른 사용자가 있었는지에 관계없이 사용자는 계속 가입하려고합니다. 그럼 어떡하지? 이 코드를 함수에 넣고 함수를 다시 호출하면 오류가 발생합니다.

편집 :

자동으로 고유 한 ID로 새로운 공간을 만들려면, 하나는 확실히 Firebase 기준에 push()를 사용할 수 있습니다.

하지만 그 방에 구성원을 추가하려면 위에서 설명한 문제가 남아 있습니다. 또 다른 해결책은 가입시 회원 목록에서 사용자의 priority을 설정하는 것입니다. 우선 순위를 현재 타임 스탬프로 설정하면 limit 멤버 목록 콜백을 3 (멤버)으로 할 수 있습니다. 그러나 그것은 우아하고 깨끗한 것처럼 보이지 않습니다.

+0

member_count 값을 읽을 수 없습니까? 3보다 작 으면 'join '이외의'abort '를 사용 하시겠습니까? –

+0

아니요, 두 클라이언트가 동시에 가입을 시도하면 members_count를 4로 설정하고 가입합니다. 그 후에 실제로 5 명의 고객이 방안에있게됩니다. 그리고이 시나리오는 실시간 응용 프로그램에서 매우 그렇습니다. 그렇지 않습니까? – caw

+0

연결하기 전에 수표를 찍은 후 연결 한 후에는 괜찮을 것입니다. Firebase는 실시간으로 30 밀리 초가 아닙니다.그들은 정말로 빠르지 만 당신이 말하는 30 밀리 초 지연을 좋아하지 않습니다. 그런 종류의 서버가 필요하다면 논리를 수행하고 Firebase를 사용하지 않는 서버가 필요합니다. 하지만 작동 할 수있는 한 가지 해결책은 보안 문제를 만드는 것입니다.이 보안 규칙은 'val(). children(). length === 2'인 경우 쓰기를 금지합니다. 그것은 제대로 작동합니다. –

답변

2

방당 참가자 수가 고정되어 있고 비교적 적은 경우 거래를 사용하는 것이 가장 좋습니다. 그러나, 예를 들어, 대화방에 사람마다 잘 명명 된 객체를 생성하는 것이 최선이 될 수 있습니다 같을 것이다 방을 가입

/rooms 
    /<roomid, generated by push()> 
    /users 
     one: null 
     two: null 
     three: null 

(자바 스크립트 코드가 적절 자바로 변환하시기 바랍니다) 이 서버에 값을 저지하지 못할 경우

var userid = "myuserid"; 
var ref = new Firebase("<my-firebase>.firebaseio.com/rooms/<roomid>/users"); 
ref.transaction(function(users) { 
    if (!users.one) { 
    // Claim slot 1 
    users.one = userid; 
    return users; 
    } else if (!users.two) { 
    // Claim slot 2 
    users.two = userid; 
    return users; 
    } else if (!users.three) { 
    // Claim slot 3 
    users.three = userid; 
    return users; 
    } 
    // Room is full, abort the transaction. 
    return; 
}, function(err, committed, snapshot) { 
    if (committed && !err) { 
    // Joined room successfully. 
    } else { 
    // Could not join room because it was full. 
    } 
}); 

중포 기지가 자동으로 트랜잭션 함수를 호출합니다. 당신의 중포 기지와 대한

{ 
    "rules": { 
    "rooms": { 
     "$roomid": { 
     "users": { 
      "$slot": { 
      ".write": "!data.exists()" 
      } 
     } 
     } 
    } 
    } 
} 

당신은, 포지를 통해 그래픽 디버거를 이러한 규칙을 업로드 할 수 있습니다 : 위의 코드 이외에, 당신은 이미 걸렸다 슬롯을 주장하지 못하도록 몇 가지 보안 규칙을 구현해야합니다 너는 잘 가야 해!

+0

정말 고마워요! 이것이 바로 내가 의미했던 것입니다 :)하지만 보안 규칙이 필요한 이유는 무엇입니까? (아무도 다른 사람이 그것을 수정하지 않았다면, 트랜잭션은 성공적이며 완료 콜백이 호출되고, 충돌이 발생하면 Firebase 클라이언트는 새로운 값을 검색하고 업데이트 기능을 다시 실행합니다.) 보안 규칙없이 트랜잭션을 사용할 수 있다는 것은 이해했기 때문에 아무도 데이터를 수정하지 못했습니다. 누군가가했다면 먼저 새로운 가치를 얻고 방이 비어 있는지 다시 확인할 수 있습니다. 잘못인가? – caw

+0

사용자가 채널을 다시 떠날 수 있고 다른 누군가가 자신의 슬롯을 요구할 수 있다면 매우 좋습니다. 그것은 보안 규칙없이 가능할 것입니다. 그러나 보안 규칙을 사용하면 데이터가 존재하자마자'write' 권한이 사라지기 때문에 슬롯에서 자신을 제거 할 수 없습니다. – caw

+1

맞습니다. 보안 규칙은 악의적 인 클라이언트가 다른 사람의 자리를 차지하는 것을 방지하기위한 것입니다. 그러나, 당신이 지적한대로, 그것은 또한 당신이 방에서 자신을 제거 할 수 없다는 것을 의미합니다. 이를 허용하는 보안 규칙을 삭제하거나 일부 인증 메커니즘을 통해 사용자를 로그인하는 경우 "! data.exists() || auth.id == data.val()"규칙을 변경할 수 있습니다. "자리를 요구 한 사용자 만 자신을 삭제할 수 있습니다. – Anant

관련 문제